Page 1 of 1

Comms Link Assembly Code

Posted: Mon Jan 30, 2023 7:51 am
by amenjet
I've been looking at assembly code for the comms link and have found information here:

https://www.jaapsch.net/psion/rsctrl.htm

There's an example which looks like this:

Code: Select all

clrb           ; Open for reading and writing
jsr rst_entry_point
.byte rs$open
bcs error      ; Deal with error
...            ; Now free to access the port
which is fine, except that the 'rst_entry_point' isn't defined in this document. I found it here:

https://www.retroisle.com/others/psion/ ... /comms.htm

and it looks like maybe some of the document is missing in the first (Jaap's) link. i suspect that there's an assembly INC file somewhere that has these definitions, does anyone know it's name or whereabouts? It'd be nice to have the original file, rather than one I make myself.

Andrew

Re: Comms Link Assembly Code

Posted: Fri Feb 03, 2023 5:08 am
by Lostgallifreyan
I'm not sure, but I think rst_entry_point may not be a formal definition, just a string meaning that a specifically named comms link subroutine ("RS$liput", "RS$liget", etc) is used. It may apply to any subroutine, like "AL$free" and the rest. I made a Organiser ASM code lister in Lua in 2019 that mentions "rst_entry_point" but only as part of a printed comment. The script just looked up subroutine names based on numbers in the code, so at best 'rst_entry_point' might be considered as a longwinded variable name, not a strict definition.

Re: Comms Link Assembly Code

Posted: Fri Feb 03, 2023 7:41 pm
by amenjet
It looks like it's a vector at $2174 which isn't documented in many places.

I've created this file which has the comms link definitions that I could find:

Code: Select all

; Comms Link Assembly Definitions

rsb_baud    .EQU  $2150  ; 0-9	50,75,110,150,300,600,1200,2400,4800,9600 Baud rate (transfer speed)
rsb_parity  .EQU  $2151  ; 0-4	NONE, ODD, EVEN,MARK, SPACE	Data, Parity, Stop Bit settings:transfer frame setup
rsb_bits    .EQU  $2152  ; 0-1	0 - 7 BIT DATA1 - 8 BIT DATA
rsb_stop    .EQU  $2153  ; 0-1	0 - 1 STOP BIT1 - 2 STOP BITS
rsb_hand    .EQU  $2154  ; 0-7	NONE,XON,RTS,XON+RTS,DTR,DTR+XON,DTR+RTS,ALL	Handshake mode
rsb_proto   .EQU  $2155  ; 0-2	NONE, XMODEM, PSION	File transfer protocol(off by default)
rsb_echo    .EQU  $2156  ; 0-1	LOCAL, HOSTEcho(Terminal emulation only)
rsb_width   .EQU  $2157  ; 0-250	NONE,1-250	buffer width(forced line length)
rsb_timout  .EQU  $2158  ; 0-255	NONE,1-255 seconds	LPRINT timeout

rst_reol    .EQU  $2159  ;	13,10 <CR><LF>	Receive End Of Line character(s)
rst_reof    .EQU  $215C  ;	26    <SUB>	Receive End Of File character(s)
rst_rtrn    .EQU  $215F  ;	empty	Receive Translate character(s): 1 - remove, 2 - replace first by second
rst_teol    .EQU  $2162  ;	13,10 <CR><LF>	Transmit End Of Line character(s)
rst_teof    .EQU  $2165  ;	26 <SUB>	Transmit End Of Files character(s)
rst_ttrn    .EQU  $2168  ;	empty	Transmit Translate characters: 1 - remove, 2 - replace first by second

rsb_off_del     .EQU  $216B        ;1-255 default=3	Time to off delay in characters
rsb_xoff_del    .EQU  $216C        ;1-255 default=7	Time to off delay with XON/XOFF
rsb_tcon_val    .EQU  $216D        ;0-255	Time constant value for timer 2 baud rate generation
rsb_off_ticks   .EQU  $216E        ;0-255	No. of ticks for baud rate dependent Tx off delay
rsw_off_tcon    .EQU  $216F        ;0-$FFFF	Time constant for single tick TX off delay (word)
rsb_sec_timer   .EQU  $2171        ;0-255	General purpose decrement to zero second timer (decremented once every second until zero)
                                   ;$2172	RESERVED WORD
rst_entry_point .EQU   $2174       ;	 	Entry point for assembler interface, contains a jump instruction to the driver (3 bytes).

    ;
    ; RS - Macro for assembler interface to COMMS LINK drivers
    ;

.macro    RS  function
          jsr rst_entry_point
.byte     function
.endm

rs_open  	.EQU            0    ;	Open the COMMS LINK channel
rs_close        .EQU     	1    ;	Close the COMMS LINK channel
rs_putchar      .EQU       	2    ;	Put a character to the RS232 port
rs_getchar      .EQU       	3    ;	Get a character from the RS232 port
rs_flush        .EQU     	4    ;	Flush the receive buffer
rs_setvars      .EQU       	5    ;	Set the COMMS LINK variables up after a change
rs_lprint       .EQU      	6    ;	Print a string
rs_linput       .EQU      	7    ;	Input a string
rs_licon        .EQU     	8    ;	Link layer connect call
rs_lidis        .EQU     	9    ;	Link layer disconnect call
rs_liput        .EQU     	10    ;	Link layer put a frame call
rs_liget        .EQU     	11    ;	Link layer get a frame call
I haven't tried these out yet, so there could be errors in it.

Andrew

Re: Comms Link Assembly Code

Posted: Sat Feb 04, 2023 4:39 am
by Lostgallifreyan
Ok, if it's not just an indicator that some known subroutine entry point is to be used instead, then poking the suspect address with the metaphorical big stick (on an otherwise uncommitted Organiser) might show a change that means something, but failing that, then a full disassembly of Comms Link ROM might be the only way. If nothing else, it will find hidden routines. If there isn't one that doesn't match an existing documented name, rst_entry_point can't be an explicit or unique reference. (Though the naming convention does make it look like one!)

Did you ask Jaap directly? I think if he knows, he will tell you.

Re: Comms Link Assembly Code

Posted: Sat Feb 04, 2023 2:26 pm
by amenjet
Lostgallifreyan wrote: Sat Feb 04, 2023 4:39 am Ok, if it's not just an indicator that some known subroutine entry point is to be used instead, then poking the suspect address with the metaphorical big stick (on an otherwise uncommitted Organiser) might show a change that means something, but failing that, then a full disassembly of Comms Link ROM might be the only way. If nothing else, it will find hidden routines. If there isn't one that doesn't match an existing documented name, rst_entry_point can't be an explicit or unique reference. (Though the naming convention does make it look like one!)

Did you ask Jaap directly? I think if he knows, he will tell you.
I haven't contacted Jaap, no. All past attempts to do that didn't work.

Andrew

Re: Comms Link Assembly Code

Posted: Mon Feb 06, 2023 12:23 pm
by Lostgallifreyan
Mine don't always.. Still, a direct tech question might raise the odds in favour. That worked for me at times. Anyway, I don't really know what that rst-thing is, but I do remember Jaap once saying that listing the code is a vital starting point to find out if some unknown routine can be called. We always have one advantage: the code is not very large. Looking for the RET's was how I found constraints on how much I needed to examine, sometimes.

When I worked on the Psion code for pack handling, and also for the timesync bit, I used direct calls to the Comms Link functions, so I assumed those where the 'entry points', and that the rst-thing was just a way of saying do that... I just did what the existing code would do when using the same functions. I didn't look for undocumented functions, so I don't know if there might be some.

Re: Comms Link Assembly Code

Posted: Wed Apr 05, 2023 3:58 pm
by Lostgallifreyan
amenjet wrote: Mon Jan 30, 2023 7:51 am I've been looking at assembly code for the comms link and have found information here:

http://https..www.jaapsch.net/psion/rsctrl.htm

There's an example which looks like this:

Code: Select all

clrb           ; Open for reading and writing
jsr rst_entry_point
.byte rs$open
bcs error      ; Deal with error
...            ; Now free to access the port
which is fine, except that the 'rst_entry_point' isn't defined in this document. I found it here:

http://https..www.retroisle.com/others/psion/organiser2/OriginalDocs/comms.htm

and it looks like maybe some of the document is missing in the first (Jaap's) link. i suspect that there's an assembly INC file somewhere that has these definitions, does anyone know it's name or whereabouts? It'd be nice to have the original file, rather than one I make myself.

Andrew
I have been having A Day... I came back here looking for CL services because my references are a mess here. I found something in the doc you linked to (it will help me experiment with 'MSF' time signalling using a flow control line).

While I was at it, I had to think about that rst_entry_point thing, and I'm even more certain that this is a macro already in the machine, designed to use a single 'vector' number and calling the same code at same place to redirect to the service you want, that being the notion, I think... Given the need for many small calls for port actions, each with the overhead to set up a call, this would be useful to keep instruction loops small and fast.

Re: Comms Link Assembly Code

Posted: Wed Apr 05, 2023 4:29 pm
by Lostgallifreyan
This might be useful if you haven't already made something that does this:

Code: Select all

function Main()
  N=0  S=0  E=0  R=0  T={}  X=0  SWI=0
  --C=DataLoad("Y_IN.bin")
  C=DataLoad(FileCall())
  S=tonumber(GetInput("Starting offset","Enter a hexadecimal number for START of code:",""),16)
  if (S==nil)  then  os.exit()  end  S=S+1
  E=tonumber(GetInput("Ending offset","Enter a hexadecimal number for END of code:",""),16)
  if (E==nil)  then  os.exit()  end  E=E+1
  R=tonumber(GetInput("New offset","Edit this if renumbering the offsets:",string.format("%04X",S-1)),16)
  if (R==nil)  then  os.exit()  end  R=R+1
  while S<=E do
    N=string.byte(C,S)  X=N  N=IL[X+1]  if (N==0) then  break  end
    S1=string.sub(C,S,S+N-1)  S1=string.format("%04X:   ",R-1)..Data_Hex(S1)  S2=IM[X+1]
    if (X>=32 and X<=47 or X==141) then
      X=string.byte(C,S+1)  if (X>127) then  X=X-256  end
      S2=S2..string.format("%+i",X)
    end
    if (X==63) then  SWI=string.byte(C,S+1)  S2=S2.." "..SM[SWI+1]                                          --Add names for Software Interrupt calls.
      if (SWI==11) then S1=S1..Data_Hex(string.char(string.byte(C,S+2)))  N=N+1  end                        --
    end
    if (X==189 and string.byte(C,S+1)*256+string.byte(C,S+2)==8564) then                                    --Check for jump to CL subroutines at $2174.
      X=string.byte(C,S+3)  S1=S1..Data_Hex(string.char(X))  N=N+1                                          --Get the extra byte and increase N by 1.
      S2="JSR rst_entry_point     Jump to Comms Link function "..X..", "..CL[X+1].."."                      --Prepare the mnemonic and a full comment.
    end
    table.insert(T,S1..string.rep(" ",24-(3*N))..S2)  S=S+N  R=R+N
    if (X==63 and SWI==111) then                                                                            --If SWI is UT$DISP, print the inline string.
      N=0  repeat N=N+1 until  string.byte(C,S+N-1)==0
      S1=string.sub(C,S,S+N-2)
      X=Data_Hex(S1).."00"  local L=1
      S1="             Print \""..string.gsub(S1,"\"","\"+QUOTE+\"").."\"."                                 --Fix literal quotes, then quote the string.
      S1=string.gsub(S1,".",
        function(V)  V=string.byte(V)  if (V<32) then  return "\"+"..CC[V+1].."+\""  end  end               --Print control characters by STANDARD names.
      )
      S1=string.gsub(S1,"\"\"%+","")  S1=string.gsub(S1,"%+\"\"","")                                        --Clean up surplus quotes and + signs.
      T[table.getn(T)]=T[table.getn(T)]..S1
      while L<=string.len(X) do
        table.insert(T,"        "..string.sub(X,L,L+24-1))  L=L+24
      end
      S=S+N  R=R+N
    end
  end
  C=TextFile(T,"\r\n")  C=string.gsub(C,"(39 +RTS)","%1\r\n\r\n")
  DataSave("Z_OUT.txt",C)
  os.exit()
end

--==========      GUI  Functions   =============--

function FileCall()
  local FilePane=wx.wxFileDialog(wx.NULL,"Psion Organiser machine code disassembler","","","All files|*.*",wx.wxOPEN)
  FilePane:Centre()
  if (FilePane:ShowModal()==wx.wxID_OK) then  return FilePane:GetPath()  else os.exit()  end
  FilePane:Destroy()
end

function GetInput(T,M,zz)  local N
  local InputBox=wx.wxTextEntryDialog(wx.NULL,M,T);  InputBox:SetValue(zz)
  if (InputBox:ShowModal()~=wx.wxID_OK) then  N=""  else  N=InputBox:GetValue()  end
  InputBox:Destroy()
  return N
end

function AlertMsg(M,T,I,YN)  local F="File Error:"                      -- General alert. M=Message. T=Title, "File Error:" as default.
    return wx.wxMessageBox(M,T or F,wx.wxOK+(YN or 0)*6+256*2^I)        -- YN=1=Yes/No. I=0/1/2/3=Exclamation/Error/Question/Information.
end

--==========    Common  Functions   ============--

function DataLoad(F)
    F=assert(io.open(F,"rb"))  local D=F:read("*a")  F:close()  return D
end

function DataSave(F,D)
    F=assert(io.open(F,"wb"))  F:write(D)  F:close()
end

function TextFile(T,N)  --Table, Newline.
  return table.concat(T,N)..N
end

function Data_Hex(S)
  return string.gsub(S,".",function(X)
    return string.format("%02X ",string.byte(X)) end)
end

--========================================================    Bulk Data tables   =========================================================--

  IL={1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
      1,0,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,0,0,1,1,0,1,1,1,1,1,0,1,1,0,1,2,3,3,2,2,3,2,2,2,2,2,3,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
      2,2,2,3,2,2,2,0,2,2,2,2,3,2,3,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
      2,2,2,3,2,2,2,0,2,2,2,2,3,0,3,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}
  IM={"TRAP","NOP","","","LSRD","ASLD","TAP","TPA","INX","DEX","CLV","SEV","CLC","SEC","CLI","SEI","SBA","CBA","","","","","TAB","TBA",
      "XGDX","DAA","SLP","ABA","","","","","BRA ","BRN ","BHI ","BLS ","BCC ","BCS ","BNE ","BEQ ","BVC ","BVS ","BPL ","BMI ","BGE ",
      "BLT ","BGT ","BLE ","TSX","INS","PULA","PULB","DES","TXS","PSHA","PSHB","PULX","RTS","ABX","RTI","PSHX","MUL","WAI","SWI","NEGA",
      "","","COMA","LSRA","","RORA","ASRA","ASLA","ROLA","DECA","","INCA","TSTA","","CLRA","NEGB","","","COMB","LSRB","","RORB","ASRB",
      "ASLB","ROLB","DECB","","INCB","TSTB","","CLRB","NEG d,X","AIM #,d,X","OIM #,d,X","COM d,X","LSR d,X","EIM #,d,X","ROR d,X","ASR d,X",
      "ASL d,X","ROL d,X","DEC d,X","TIM #,d,X","INC d,X","TST d,X","JMP d,X","CLR d,X","NEG mm","AIM #,0m","OIM #,0m","COM mm","LSR mm",
      "EIM #,0m","ROR mm","ASR mm","ASL mm","ROL mm","DEC mm","TIM #,0m","INC mm","TST mm","JMP mm","CLR mm","SUBA #","CMPA #","SBCA #",
      "SUBD ##","ANDA #","BITA #","LDAA #","","EORA #","ADCA #","ORAA #","ADDA #","CPX ##","BSR ","LDS ##","","SUBA 0m","CMPA 0m","SBCA 0m",
      "SUBD 0m","ANDA 0m","BITA 0m","LDAA 0m","STAA 0m","EORA 0m","ADCA 0m","ORAA 0m","ADDA 0m","CPX 0m","JSR 0m","LDS 0m","STS 0m","SUBA d,X",
      "CMPA d,X","SBCA d,X","SUBD d,X","ANDA d,X","BITA d,X","LDAA d,X","STAA d,X","EORA d,X","ADCA d,X","ORAA d,X","ADDA d,X","CPX d,X",
      "JSR d,X","LDS d,X","STS d,X","SUBA mm","CMPA mm","SBCA mm","SUBD mm","ANDA mm","BITA mm","LDAA mm","STAA mm","EORA mm","ADCA mm",
      "ORAA mm","ADDA mm","CPX mm","JSR mm","LDS mm","STS mm","SUBB #","CMPB #","SBCB #","ADDD ##","ANDB #","BITB #","LDAB #","","EORB #",
      "ADCB #","ORAB #","ADDB #","LDD ##","","LDX ##","","SUBB 0m","CMPB 0m","SBCB 0m","ADDD 0m","ANDB 0m","BITB 0m","LDAB 0m","STAB 0m",
      "EORB 0m","ADCB 0m","ORAB 0m","ADDB 0m","LDD 0m","STD 0m","LDX 0m","STX 0m","SUBB d,X","CMPB d,X","SBCB d,X","ADDD d,X","ANDB d,X",
      "BITB d,X","LDAB d,X","STAB d,X","EORB d,X","ADCB d,X","ORAB d,X","ADDB d,X","LDD d,X","STD d,X","LDX d,X","STX d,X","SUBB mm","CMPB mm",
      "SBCB mm","ADDD mm","ANDB mm","BITB mm","LDAB mm","STAB mm","EORB mm","ADCB mm","ORAB mm","ADDB mm","LDD mm","STD mm","LDX mm","STX mm"}
  SM={"AL$free","AL$grab","AL$grow","AL$repl","AL$shnk","AL$size","AL$zero","BT$nmdn","BT$nmen","BT$nof","BT$non","BT$pprg","BT$swof",
      "BZ$alrm","BZ$bell","BZ$tone","DP$emit","DP$prnt","DP$rest","DP$save","DP$stat","DP$view","DP$wrdy","DV$boot","DV$cler","DV$lkup",
      "DV$load","DV$vect","ED$edit","ED$epos","ED$view","ER$lkup","ER$mess","FL$back","FL$bcat","FL$bdel","FL$bopn","FL$bsav","FL$catl",
      "FL$copy","FL$cret","FL$deln","FL$eras","FL$ffnd","FL$find","FL$frec","FL$next","FL$open","FL$pars","FL$read","FL$rect","FL$renm",
      "FL$rset","FL$setp","FL$size","FL$writ","FN$atan","FN$cos","FN$exp","FN$ln","FN$log","FN$powr","FN$rnd","FN$sin","FN$sqrt","FN$tan",
      "IT$gval","IT$radd","IT$strt","IT$tadd","KB$brek","KB$flsh","KB$getk","KB$init","KB$stat","KB$test","KB$uget","LG$newp","LG$rled",
      "LN$strt","MN$disp","MT$btof","MT$fadd","MT$fbdc","MT$fbex","MT$fbgn","MT$fbin","MT$fdiv","MT$fmul","MT$fngt","MT$fsub","PK$pkof",
      "PK$qadd","PK$rbyt","PK$read","PK$rwrd","PK$sadd","PK$save","PK$setp","PK$skip","RM$runp","TL$addi","TL$cpyx","TL$deli","TL$xxmd",
      "TM$dayv","TM$tget","TM$updt","TM$wait","UT$cpyb","UT$ddsp","UT$disp","UT$entr","UT$fill","UT$icpb","UT$isbf","UT$leav","UT$sdiv",
      "UT$smul","UT$splt","UT$udiv","UT$umul","UT$utob","UT$xcat","UT$xtob","UT$ysno","UT$cdsp*","TL$rstr*","TL$lset*","BT$toff*","DP$mset*",
      "DP$cset*","DP$cprn*","DP$udg*","MN$xdsp*","MN$1dsp*","MN$titl*","FN$sum*","FN$mean*","FN$var*","FN$std*","FN$min*","FN$max*","FL$wpar*",
      "FL$wcat*","FL$wcpy*","FL$wdel*","FL$wfnd*","UT$wild*","TM$ndys*","TM$week*","TM$dnam*","FL$getx*","FL$valx*","LN$xstt*","TL$zzmd*",
      "XT$dirm*","FL$ncat*","AM$entr*","NT$entr*","CA$entr*","XT$entr*","XT$bar*","DP$pvew*","TI$entr*","UT$sort*","WL$entr*","DI$entr*",
      "XF$entr*","ER$prnt*","TM$mnam*","LG$edit*","FN$asin*","FN$acos*","XF$sort*","LG$entr*","FL$fdel*","KB$conk*","UT$cmpb*","TM$tset*"}
  CL={"RS$open","RS$close","RS$putchar","RS$getchar","RS$flush","RS$setvars","RS$lprint","RS$linput","RS$licon","RS$lidis","RS$liput","RS$liget"}
  CC={"UDG_0","UDG_1","UDG_2","UDG_3","UDG_4","UDG_5","UDG_6","UDG_7","DEL","TAB","LF","HOME","CLS","CR","CLR_1","CLR_2","BEEP","RFR_1/2",
      "RFR_1","RFR_2","RFR_3","RFR_4","CLR_3","CLR_4","DOTS_2","DOTS_3","CLR_E","CHR$(11)","CHR$(12)","CHR$(13)","CHR$(14)","CHR$(15)"}

--=======================================================    End  Of  Script   ===========================================================--

Main()
If you run that with wxLua it will open an Organiser machine code binary file and list the doings in an output file like ASM. It mentions the rst_entry_point. I can't remember the context for making this anymore, but it was basically to help examine what existing Psion code is up to. It can be set to limit which chunk of the binary file you want to extract a listing for.

I have found it useful even if all I want to know is whether something IS code or not. :) If it's not, the output is garbage, but the same is true of any disassembler, even Win32 DASM...

Re: Comms Link Assembly Code

Posted: Wed Apr 05, 2023 6:27 pm
by Lostgallifreyan
An example of output from that disassembler, with some comments added:

Code: Select all

013A:   BD 21 74 0B             JSR rst_entry_point     Jump to Comms Link function 11, RS$liget.
013E:   25 D3                   BCS -45                 If 'carry' flag is set, jump -45 bytes. (To display 'Abort: Code '...)
0140:   39                      RTS                     Return.


0141:   BD 21 74 0A             JSR rst_entry_point     Jump to Comms Link function 10, RS$liput.
0145:   25 CC                   BCS -52                 If 'carry' flag is set, jump -52 bytes. (To display 'Abort: Code '...)
0147:   39                      RTS                     Return.


0148:   36                      PSHA                    Push byte in register A onto the stack.
0149:   BD 21 74 08             JSR rst_entry_point     Jump to Comms Link function 8, RS$licon.
014D:   32                      PULA                    Pull byte from the stack into register A.
014E:   39                      RTS                     Return.


014F:   C6 01                   LDAB #                  Load register B with $01.
0151:   BD 21 74 01             JSR rst_entry_point     Jump to Comms Link function 1, RS$close. (Port closed and turned off.)
0155:   39                      RTS                     Return.


0156:   5F                      CLRB                    Clear register B.
0157:   BD 21 74 00             JSR rst_entry_point     Jump to Comms Link function 0, RS$open. (TX and RX.)
015B:   39                      RTS                     Return.
This is part of a disassembly of 'UNMAKE'. It shows how the macro is used to jump to a comms link subroutine. The calls are not made directly. Assume all registers are trashed, so stack anything you might want back.

Re: Comms Link Assembly Code

Posted: Wed Apr 05, 2023 7:45 pm
by amenjet
I've started using the Ghidra disassembler/decompiler from the NSA (yes, the NSA). It's complicated but pretty good. It can decompile into sort of C, which isn't really re-compile-able unfortunately. It handles assembly really well. I added Psion Organiser things to it so it can understand 6303 plus the Psion OS calls etc.
The add-on is here:

https://github.com/blackjetrock/ghidra-6303

The rst_entry_point is indeed a vector in the Organiser.

Andrew