Z88dk: z80asm: DEFC constants with expressions based on PHASED labels were being patched (was: RC2014 off by one issue)

Created on 19 Mar 2018  路  14Comments  路  Source: z88dk/z88dk

I'm building a CP/M based on the RC2014 pageable ROM and 64kB RAM modules, together with the IDE drive. The goal is to allow CP/M to load from ROM but using FATFS formatted drives.

The process is to have the CCP/BDOS and the BIOS loaded into the correct places out of ROM using a preamble and then boot into a monitor also in ROM. The user can then configure the FATFS files that are required to be the CP/M drives. Then the ROM is paged out, a new Page 0 is created, and then CCP/BDOS is started.

The issue is that somehow the CCP PHASE is being created with the first byte incorrect. The first byte of the CCP PHASE is being written as a $00 byte.

EDIT: It is an assembler issue. further notes below. The incorrectly overwritten byte seems to decrement by one for each byte prepended before the start of the PHASE. i.e. if 8 bytes are prepended, then the first byte is overwritten as $F8 after 7 correct prepends. If two bytes are prepended before the PHASE, then the first byte is overwritten as $FE following one correct prepend..

Listing of CCP below

1     0000              MODULE cpm22_asm
2     0000              LINE -1, "cpm22.asm"
-1    0000              
0     0000              
1     0000              ;
2     0000              ;
3     0000              ;**************************************************************
4     0000              ;*
5     0000              ;*             C P / M   version   2 . 2
6     0000              ;*
7     0000              ;*   Reconstructed from memory image on February 27, 1981
8     0000              ;*
9     0000              ;*                by Clark A. Calkins
10    0000              ;*
11    0000              ;**************************************************************
12    0000              ;
13    0000              ;
14    0000              ; Converted to z88dk z80asm for RC2014 by
15    0000              ; Phillip Stevens @feilipu https://feilipu.me
16    0000              ; March 2018
17    0000              ;
18    0000              
19    0000              SECTION rodata_user              ;read only user
20    0000              
21    0000              ;------------------------------------------------------------------------------
22    0000              ; location setting
23    0000              ;------------------------------------------------------------------------------
24    0000              
25    0000              PUBLIC  __COMMON_AREA_PHASE_CCP_BDOS    ;base of ccp
26    0000              defc    __COMMON_AREA_PHASE_CCP_BDOS    = 0xD800
27    0000              
28    0000              ;------------------------------------------------------------------------------
29    0000              ; start of definitions
30    0000              ;------------------------------------------------------------------------------
31    0000              
32    0000              EXTERN  _cpm_iobyte
33    0000              EXTERN  _cpm_cdisk
34    0000              EXTERN  _cpm_ccp_tfcb
35    0000              EXTERN  _cpm_ccp_tbuff
36    0000              EXTERN  _cpm_ccp_tbase
37    0000              
38    0000              DEFC    IOBYTE      =       _cpm_iobyte     ;i/o definition byte
39    0000              DEFC    TDRIVE      =       _cpm_cdisk      ;current drive name and user number
40    0000              DEFC    ENTRY       =       _cpm_bdos_head  ;entry point for the cp/m bdos
41    0000              DEFC    TFCB        =       _cpm_ccp_tfcb   ;default file control block
42    0000              DEFC    TBUFF       =       _cpm_ccp_tbuff  ;i/o buffer and command line storage
43    0000              DEFC    TBASE       =       _cpm_ccp_tbase  ;transient program storage area
44    0000              
45    0000              ;
46    0000              ;   Set control character equates.
47    0000              ;
48    0000              DEFC    CNTRLC      =   03H     ;control-c
49    0000              DEFC    CNTRLE      =   05H     ;control-e
50    0000              DEFC    BS          =   08H     ;backspace
51    0000              DEFC    TAB         =   09H     ;tab
52    0000              DEFC    LF          =   0AH     ;line feed
53    0000              DEFC    FF          =   0CH     ;form feed
54    0000              DEFC    CR          =   0DH     ;carriage return
55    0000              DEFC    CNTRLP      =   10H     ;control-p
56    0000              DEFC    CNTRLR      =   12H     ;control-r
57    0000              DEFC    CNTRLS      =   13H     ;control-s
58    0000              DEFC    CNTRLU      =   15H     ;control-u
59    0000              DEFC    CNTRLX      =   18H     ;control-x
60    0000              DEFC    CNTRLZ      =   1AH     ;control-z (end-of-file mark)
61    0000              DEFC    DEL         =   7FH     ;rubout
62    0000              
63    0000              ;
64    0000              ;   Set origin for CP/M
65    0000              ;
66    0000              PUBLIC  _rodata_cpm_ccp_head
67    0000              _rodata_cpm_ccp_head:           ;origin of the cpm ccp in rodata
68    0000              
69    0000              PHASE   __COMMON_AREA_PHASE_CCP_BDOS
70    D800              
71    D800              PUBLIC  _cpm_ccp_head
72    D800              _cpm_ccp_head:                  ;origin of the cpm ccp
73    D800              
74    D800              CBASE:
75    D800  C3 45 DB        JP    COMMAND       ;execute command processor (ccp).
76    D803  C3 41 DB        JP    CLEARBUF      ;entry to empty input buffer before starting ccp.
77    D806              
78    D806              ;
79    D806              ;   Standard cp/m ccp input buffer. Format is (max length),
80    D806              ;   (actual length), (char #1), (char #2), (char #3), etc.
81    D806              ;
82    D806              INBUFF:
83    D806  7F              DEFB    127         ;length of input buffer.
84    D807  00              DEFB    0           ;current length of contents.
85    D808  43 6F 70 79 72 69 67 68 74 20 31 39 37 39 20 28 63 29 20 62 79 20 44 69 67 69 74 61 6C 20 52 65 
      D828  73 65 61 72 63 68 
                            DEFM    "Copyright 1979 (c) by Digital Research"
86    D82E  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
      D84E  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
      D86E  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
                            DEFS    89,0

Excerpt of the map file

_code_preamble_head             = $00AB ; addr, public, , cpm22preamble_asm, code_crt_init, cpm22preamble.asm:24
__COMMON_AREA_PHASE_CCP_BDOS    = $D800 ; const, public, , cpm22_asm, rodata_user, cpm22.asm:26
_rodata_cpm_ccp_head            = $4E7C ; addr, public, , cpm22_asm, rodata_user, cpm22.asm:67
_cpm_ccp_head                   = $D800 ; const, public, , cpm22_asm, rodata_user, cpm22.asm:72
_cpm_ccp_tail                   = $DF98 ; const, public, , cpm22_asm, rodata_user, cpm22.asm:1397
_cpm_ccp_data_head              = $DF98 ; const, public, , cpm22_asm, rodata_user, cpm22.asm:1401
_cpm_ccp_data_tail              = $DFF0 ; const, public, , cpm22_asm, rodata_user, cpm22.asm:1436
_cpm_bdos_head                  = $E000 ; const, public, , cpm22_asm, rodata_user, cpm22.asm:1449
_cpm_bdos_tail                  = $ED60 ; const, public, , cpm22_asm, rodata_user, cpm22.asm:4069
_cpm_bdos_data                  = $ED60 ; const, public, , cpm22_asm, rodata_user, cpm22.asm:4080
_cpm_bdos_data_tail             = $ED63 ; const, public, , cpm22_asm, rodata_user, cpm22.asm:4086
_cpm_bdos_bss_bridge            = $ED63 ; const, public, , cpm22_asm, rodata_user, cpm22.asm:4089
_cpm_bdos_bss_head              = $ED63 ; const, public, , cpm22_asm, bss_user, cpm22.asm:4102
_cpm_bdos_bss_tail              = $EDEB ; const, public, , cpm22_asm, bss_user, cpm22.asm:4177
__COMMON_AREA_PHASE_BIOS        = $EE00 ; const, public, , cpm22bios_asm, rodata_user, cpm22bios.asm:17

Further excerpt of the map file

phillip@SilverQuad:~/Z80/RC2014/ROMs/CPM-IDE$ grep \$4E7 rc2014-cpm22.map
___str_1                        = $4E72 ; addr, local, , ff_c, rodata_compiler, ./ff.c:2972
___str_2                        = $4E76 ; addr, local, , ff_c, rodata_compiler, ./ff.c:2976
_rodata_cpm_ccp_head            = $4E7C ; addr, public, , cpm22_asm, rodata_user, cpm22.asm:67
__rodata_compiler_tail          = $4E7C ; const, public, def, , ,
__rodata_user_head              = $4E7C ; const, public, def, , ,

Compile line

phillip@SilverQuad:~/Z80/RC2014/ROMs/CPM-IDE$ zcc +rc2014 -SO3 --opt-code-size -subtype=acia -m --list -llib/rc2014/ff --c-code-in-asm --max-allocs-per-node20000 @cpm22.lst -o rc2014-cpm22 -create-app

The attached screenshot shows the $D800 origin of the CCP as $00. Also, there is a $00 byte at the _rodata_cpm_ccp_head, which indicates the linkage for the HEX file is being prepared incorrectly.

screenshot from 2018-03-19 23-25-32

Also using the ff library to support FATFS on IDE.

bug z80asm

Most helpful comment

This one was hairy!

IF a DEFC constant (ENTRY in cpm22bios.asm) was defined equal to a label (_cpm_bdos_head)
AND the label (_cpm_bdos_head) was in a PHASED block, therefore a constant and not an address,
THEN the expression value (_cpm_bdos_head) was being patched to the object file at the ASMPC
where it was referred to (DEFC ENTRY = _cpm_bdos_head was at ASMPC = 1, i.e. after the $55)

The $FF was the low byte, the high byte was later overwritten in the object file by the JP COMMAND
argument.

Fixed.

Thanks for reporting!

All 14 comments

Yes something looks wrong there. I'll try a build tonight. It would be interesting to see if the overwritten byte is also present in the binary or if it's just the hex file that is affected.

Yes. It is also there in the binary.

I moved the section to rodata_driver, which puts my driver in a different order. Just to experiment.

The first byte is $492E. It is indeed wrong in the binary and HEX again.

1     0000              MODULE cpm22_asm
2     0000              LINE -1, "cpm22.asm"
-1    0000              
0     0000              
1     0000              ;
2     0000              ;
3     0000              ;**************************************************************
4     0000              ;*
5     0000              ;*             C P / M   version   2 . 2
6     0000              ;*
7     0000              ;*   Reconstructed from memory image on February 27, 1981
8     0000              ;*
9     0000              ;*                by Clark A. Calkins
10    0000              ;*
11    0000              ;**************************************************************
12    0000              ;
13    0000              ;
14    0000              ; Converted to z88dk z80asm for RC2014 by
15    0000              ; Phillip Stevens @feilipu https://feilipu.me
16    0000              ; March 2018
17    0000              ;
18    0000              
19    0000              SECTION rodata_driver           ;read only driver (code)
20    0000              
21    0000              ;------------------------------------------------------------------------------
22    0000              ; location setting
23    0000              ;------------------------------------------------------------------------------
24    0000              
25    0000              PUBLIC  __COMMON_AREA_PHASE_CCP_BDOS    ;base of ccp
26    0000              defc    __COMMON_AREA_PHASE_CCP_BDOS    = 0xD800
27    0000              
28    0000              ;------------------------------------------------------------------------------
29    0000              ; start of definitions
30    0000              ;------------------------------------------------------------------------------
31    0000              
32    0000              EXTERN  _cpm_iobyte
33    0000              EXTERN  _cpm_cdisk
34    0000              EXTERN  _cpm_ccp_tfcb
35    0000              EXTERN  _cpm_ccp_tbuff
36    0000              EXTERN  _cpm_ccp_tbase
37    0000              
38    0000              DEFC    IOBYTE      =       _cpm_iobyte     ;i/o definition byte
39    0000              DEFC    TDRIVE      =       _cpm_cdisk      ;current drive name and user number
40    0000              DEFC    ENTRY       =       _cpm_bdos_head  ;entry point for the cp/m bdos
41    0000              DEFC    TFCB        =       _cpm_ccp_tfcb   ;default file control block
42    0000              DEFC    TBUFF       =       _cpm_ccp_tbuff  ;i/o buffer and command line storage
43    0000              DEFC    TBASE       =       _cpm_ccp_tbase  ;transient program storage area
44    0000              
45    0000              ;
46    0000              ;   Set control character equates.
47    0000              ;
48    0000              DEFC    CNTRLC      =   03H     ;control-c
49    0000              DEFC    CNTRLE      =   05H     ;control-e
50    0000              DEFC    BS          =   08H     ;backspace
51    0000              DEFC    TAB         =   09H     ;tab
52    0000              DEFC    LF          =   0AH     ;line feed
53    0000              DEFC    FF          =   0CH     ;form feed
54    0000              DEFC    CR          =   0DH     ;carriage return
55    0000              DEFC    CNTRLP      =   10H     ;control-p
56    0000              DEFC    CNTRLR      =   12H     ;control-r
57    0000              DEFC    CNTRLS      =   13H     ;control-s
58    0000              DEFC    CNTRLU      =   15H     ;control-u
59    0000              DEFC    CNTRLX      =   18H     ;control-x
60    0000              DEFC    CNTRLZ      =   1AH     ;control-z (end-of-file mark)
61    0000              DEFC    DEL         =   7FH     ;rubout
62    0000              
63    0000              ;
64    0000              ;   Set origin for CP/M
65    0000              ;
66    0000              PUBLIC  _rodata_cpm_ccp_head
67    0000              _rodata_cpm_ccp_head:           ;origin of the cpm ccp in rodata
68    0000              
69    0000              PHASE   __COMMON_AREA_PHASE_CCP_BDOS
70    D800              
71    D800              PUBLIC  _cpm_ccp_head
72    D800              _cpm_ccp_head:                  ;origin of the cpm ccp
73    D800              
74    D800              CBASE:
75    D800  C3 45 DB        JP    COMMAND       ;execute command processor (ccp).
76    D803  C3 41 DB        JP    CLEARBUF      ;entry to empty input buffer before starting ccp.
77    D806              
78    D806              ;
79    D806              ;   Standard cp/m ccp input buffer. Format is (max length),
80    D806              ;   (actual length), (char #1), (char #2), (char #3), etc.
81    D806              ;
82    D806              INBUFF:
83    D806  7F              DEFB    127         ;length of input buffer.
84    D807  00              DEFB    0           ;current length of contents.
85    D808  43 6F 70 79 72 69 67 68 74 20 31 39 37 39 20 28 63 29 20 62 79 20 44 69 67 69 74 61 6C 20 52 65 
      D828  73 65 61 72 63 68 
                            DEFM    "Copyright 1979 (c) by Digital Research"
86    D82E  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
      D84E  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
      D86E  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
                            DEFS    89,0
phillip@SilverQuad:~/Z80/RC2014/ROMs/CPM-IDE$ grep \$492 rc2014-cpm22.map
l_f_getfree_00131               = $4926 ; addr, local, , ff_c, code_compiler, ./ff.c:6202
_rodata_cpm_ccp_head            = $492E ; addr, public, , cpm22_asm, rodata_driver, cpm22.asm:67
__code_compiler_tail            = $492E ; const, public, def, , ,
__code_user_head                = $492E ; const, public, def, , ,
__code_user_tail                = $492E ; const, public, def, , ,
__rodata_driver_head            = $492E ; const, public, def, , ,

screenshot from 2018-03-20 05-40-43

screenshot from 2018-03-20 05-37-24

What is the compile line you are using?

phillip@SilverQuad:~/Z80/RC2014/ROMs/CPM-IDE/$ zcc +rc2014 -SO3 --opt-code-size -subtype=acia -m --list -llib/rc2014/ff --c-code-in-asm --max-allocs-per-node20000 @cpm22.lst -o rc2014-cpm22 -create-app

Also, I have tweaked the ff build to include some additional functions needed to get file and path info.
A new z88dk-lib +rc2014 -f ff is required to install this build.

Unrelated (probably).

The ALIGN keyword doesn't work in either the second PHASE or second SECTION in a file. Not sure which, so I haven't raised an issue until I'm clear about the cause, and so I have just avoided it twice.

If it helps, I reassembled with the option -Cl--split-bin, and the binary rc2014-cpm22_rodata_driver.bin is incorrect, with $00 as the first byte. So the listing of cpm22.asm.lis is correct, but the binary is wrong. It is not the linker at fault.

screenshot from 2018-03-20 17-55-29

It gets more interesting...

19    0000              SECTION rodata_driver           ;read only driver (code)
20    0000              
21    0000              
22    0000  55 00       testing:  defw    $55
23    0002              
24    0002              ;------------------------------------------------------------------------------
25    0002              ; location setting
26    0002              ;------------------------------------------------------------------------------
27    0002              
28    0002              PUBLIC  __COMMON_AREA_PHASE_CCP_BDOS    ;base of ccp
29    0002              defc    __COMMON_AREA_PHASE_CCP_BDOS    = 0xD800
30    0002              
31    0002              ;------------------------------------------------------------------------------
32    0002              ; start of definitions
33    0002              ;------------------------------------------------------------------------------
34    0002              

66    0002              ;
67    0002              ;   Set origin for CP/M
68    0002              ;
69    0002              PUBLIC  _rodata_cpm_ccp_head
70    0002              _rodata_cpm_ccp_head:           ;origin of the cpm ccp in rodata
71    0002              
72    0002              PHASE   __COMMON_AREA_PHASE_CCP_BDOS
73    D800              
74    D800              PUBLIC  _cpm_ccp_head
75    D800              _cpm_ccp_head:                  ;origin of the cpm ccp
76    D800              
77    D800              CBASE:
78    D800  C3 45 DB        JP    COMMAND       ;execute command processor (ccp).
79    D803  C3 41 DB        JP    CLEARBUF      ;entry to empty input buffer before starting ccp.

Gets this result $55 $00 $FE $45 $DB instead of $55 $00 $C3 $45 $DB

screenshot from 2018-03-20 19-36-34

and this.

18    0000              
19    0000              SECTION rodata_driver           ;read only driver (code)
20    0000              
21    0000              
22    0000  55          testing:  defb    $55
23    0001              
24    0001              ;------------------------------------------------------------------------------
25    0001              ; location setting
26    0001              ;------------------------------------------------------------------------------
27    0001              
28    0001              PUBLIC  __COMMON_AREA_PHASE_CCP_BDOS    ;base of ccp
29    0001              defc    __COMMON_AREA_PHASE_CCP_BDOS    = 0xD800
30    0001              
31    0001              ;------------------------------------------------------------------------------
32    0001              ; start of definitions
33    0001              ;------------------------------------------------------------------------------
34    0001              

66    0001              ;
67    0001              ;   Set origin for CP/M
68    0001              ;
69    0001              PUBLIC  _rodata_cpm_ccp_head
70    0001              _rodata_cpm_ccp_head:           ;origin of the cpm ccp in rodata
71    0001              
72    0001              PHASE   __COMMON_AREA_PHASE_CCP_BDOS
73    D800              
74    D800              PUBLIC  _cpm_ccp_head
75    D800              _cpm_ccp_head:                  ;origin of the cpm ccp
76    D800              
77    D800              CBASE:
78    D800  C3 45 DB        JP    COMMAND       ;execute command processor (ccp).
79    D803  C3 41 DB        JP    CLEARBUF      ;entry to empty input buffer before starting ccp.
80    D806              

Gets this result $55 $FF $45 $DB instead of $55 $C3 $45 $DB

screenshot from 2018-03-20 19-39-04

The ALIGN keyword doesn't work in either the second PHASE or second SECTION in a file. Not sure which, so I haven't raised an issue until I'm clear about the cause, and so I have just avoided it twice.

It looks like ALIGN is anchored to the current section and is (unexpectedly) unaffected by the PHASE. You would expect ALIGN to work within the current PHASE.

So the listing of cpm22.asm.lis is correct, but the binary is wrong. It is not the linker at fault.

It is a bug in the linker because it's outputting the incorrect raw binaries before appmake gets hold of it. It is odd that the .lis file is correct but that's also just raw assembled bytes before the linker sorts in sections and patches external symbols. Some patching error might be at work.

So, the linker generates the binary files, before appmake gets them?
Of course... otherwise the jump locations wouldn't be filled in (and they are). Doh.
Therefore shift the blame back to the linker... yes.

Will change the issue title back...

@pauloscustodio

This one's a bit odd. The error is in the object file before the linker patches extern symbols.
The problem file is cpm22.asm. The linker is overwriting the $c3 in the jump at label CBASE and the overwrite value is different if stuff is inserted before the label. So I thought it was a patching error but that's not the case because the error is already present in the object file.

Make object file:
z80asm -l cpm22.asm

Look at the the object file contents:
z80nm -a cpm22.o | more

At offset 0 the sequence of bytes is:

  Code: 5475 bytes (section rodata_driver)
    C $0000: 55 FF 45 DB C3 41 DB 7F 00 43 6F 70 79 72 69 67

The FF has overwritten the C3 opcode for jump.

Here is the corresponding lis file:

22    0000  55          testing:  defb    $55
23    0001              
24    0001              ;------------------------------------------------------------------------------
25    0001              ; location setting
26    0001              ;------------------------------------------------------------------------------
27    0001              
28    0001              PUBLIC  __COMMON_AREA_PHASE_CCP_BDOS    ;base of ccp
29    0001              defc    __COMMON_AREA_PHASE_CCP_BDOS    = 0xD800
30    0001              
31    0001              ;------------------------------------------------------------------------------
32    0001              ; start of definitions
33    0001              ;------------------------------------------------------------------------------
34    0001              
35    0001              EXTERN  _cpm_iobyte
36    0001              EXTERN  _cpm_cdisk
37    0001              EXTERN  _cpm_ccp_tfcb
38    0001              EXTERN  _cpm_ccp_tbuff
39    0001              EXTERN  _cpm_ccp_tbase
40    0001              
41    0001              DEFC    IOBYTE      =       _cpm_iobyte     ;i/o definition byte
42    0001              DEFC    TDRIVE      =       _cpm_cdisk      ;current drive name and user number
43    0001              DEFC    ENTRY       =       _cpm_bdos_head  ;entry point for the cp/m bdos
44    0001              DEFC    TFCB        =       _cpm_ccp_tfcb   ;default file control block
45    0001              DEFC    TBUFF       =       _cpm_ccp_tbuff  ;i/o buffer and command line storage
46    0001              DEFC    TBASE       =       _cpm_ccp_tbase  ;transient program storage area
47    0001              
48    0001              ;
49    0001              ;   Set control character equates.
50    0001              ;
51    0001              DEFC    CNTRLC      =   03H     ;control-c
52    0001              DEFC    CNTRLE      =   05H     ;control-e
53    0001              DEFC    BS          =   08H     ;backspace
54    0001              DEFC    TAB         =   09H     ;tab
55    0001              DEFC    LF          =   0AH     ;line feed
56    0001              DEFC    FF          =   0CH     ;form feed
57    0001              DEFC    CR          =   0DH     ;carriage return
58    0001              DEFC    CNTRLP      =   10H     ;control-p
59    0001              DEFC    CNTRLR      =   12H     ;control-r
60    0001              DEFC    CNTRLS      =   13H     ;control-s
61    0001              DEFC    CNTRLU      =   15H     ;control-u
62    0001              DEFC    CNTRLX      =   18H     ;control-x
63    0001              DEFC    CNTRLZ      =   1AH     ;control-z (end-of-file mark)
64    0001              DEFC    DEL         =   7FH     ;rubout
65    0001              
66    0001              ;
67    0001              ;   Set origin for CP/M
68    0001              ;
69    0001              PUBLIC  _rodata_cpm_ccp_head
70    0001              _rodata_cpm_ccp_head:           ;origin of the cpm ccp in rodata
71    0001              
72    0001              PHASE   __COMMON_AREA_PHASE_CCP_BDOS
73    D800              
74    D800              PUBLIC  _cpm_ccp_head
75    D800              _cpm_ccp_head:                  ;origin of the cpm ccp
76    D800              
77    D800              CBASE:
78    D800  C3 45 DB        JP    COMMAND       ;execute command processor (ccp).
79    D803  C3 41 DB        JP    CLEARBUF      ;entry to empty input buffer before starting ccp.

You can see the first few bytes should be 55 C3 45 DB C3 41 DB

Therefore shift the blame back to the linker... yes.

Let's put it back on the assembler as it looks like the object file is wrong :)

It is odd that the cpm22bios.asm file doesn't do the same thing. It is essentially identical, with a jp instruction as the first byte. It has the same PHASE and SECTION construction, so it should have exactly the same error.

I didn't actually check yet, as the first jp doesn't get hit unless CP/M is running. The preamble code jumps straight to the boot: label. So I didn't check what was at 0xEE00...

EDIT. I just checked both files by separating them into different SECTIONs and adding a defs 0x08 0x76 statement before the PHASE.

The cpm22bios.asm file is correct, but the cpm22.asm file generates 7 0x76 bytes, and then one 0xF8 byte. Curious...

screenshot from 2018-03-21 17-49-19

This one was hairy!

IF a DEFC constant (ENTRY in cpm22bios.asm) was defined equal to a label (_cpm_bdos_head)
AND the label (_cpm_bdos_head) was in a PHASED block, therefore a constant and not an address,
THEN the expression value (_cpm_bdos_head) was being patched to the object file at the ASMPC
where it was referred to (DEFC ENTRY = _cpm_bdos_head was at ASMPC = 1, i.e. after the $55)

The $FF was the low byte, the high byte was later overwritten in the object file by the JP COMMAND
argument.

Fixed.

Thanks for reporting!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

feilipu picture feilipu  路  16Comments

feilipu picture feilipu  路  4Comments

Dovgalyuk picture Dovgalyuk  路  14Comments

aralbrec picture aralbrec  路  5Comments

zx70 picture zx70  路  8Comments