====== Recent WarpLink tests ======
These tests were written to test several of the wlcalc and wllist features during their development. They're all stored in https://pushbx.org/ecm/test/20260204/
===== The scriptlets =====
The basic assemble and link scriptlet looks like this (as of the most recent WarpLink revision - some of the switches require a newer revision than others). It assembles the test object file, then links it using the local ''warplink.exe'' (a link to the development repo's executable). Then it runs the linker with the /MX, /WS0, /XL, /XS, /XC, /TO=, /TL=, /I, and /XLD switches:
(nasm test$NUM.asm -f obj && ~/proj/ldos/warplink.sh /mx /ws0 /xl /xs /xc /to=wllist.obj /tl=wllist.bin /i /xld test$NUM.obj,test$NUM.exe,test$NUM.map\;)
To dump the executable image of the output file, the following scriptlet can be used:
tail --bytes +513 test$NUM.exe | podhex
To run omfdump on the temporary wllist object file:
~/proj/omfdump/omfdump wllist.obj
To hex dump the temporary wllist list file:
podhex wllist.bin
The ''dox.bat'' script is to be run from a DOS that maps the test directory to a DOS directory. It runs the debugger with its /T, /P, and /C switches to load WarpLink and enable serial I/O. The WarpLink command it runs specifies the /TL=, /TO=, /XL, /XC, and /XS switches, along with the older /MX, /WSN, and /WS0. The first parameter, ''%1'', specifies the test number to link.
ldebug /t /p /c=install,serial warplink /tl=wllist.bin /to=wllist.obj /xl /xc /xs /mx /wsn /ws0 test%1.obj,test%1.exe,test%1.map;
===== The tests =====
==== test.asm ====
This creates a code segment with a zeroed word.
section code
dw 0
==== test1.asm ====
This uses two wlcalc post-link calculations, to imitate the usual "find number of paragraphs neeeded" for a program where this is less than 64 KiB.
section code
wlcalc_word_add_15:
wlcalc_word_div_16:
global wlcalc_word_add_15
global wlcalc_word_div_16
dw label
times 26 nop
label:
==== test2.asm ====
Like the prior test, but without a label and the order of the global directives is switched. NASM still emits the "add" operation in the PUBDEF record before the "div".
section code
wlcalc_word_add_15:
wlcalc_word_div_16:
global wlcalc_word_div_16
global wlcalc_word_add_15
dw 0
==== test3.asm ====
Like the prior test but the order of the operations is changed again.
section code
wlcalc_word_div_16:
wlcalc_word_add_15:
global wlcalc_word_div_16
global wlcalc_word_add_15
dw 0
==== test4.asm ====
Again a different order of the global directives. NASM still follows the order of the labels, ignoring the differing order of the global directives.
section code
wlcalc_word_div_16:
wlcalc_word_add_15:
global wlcalc_word_add_15
global wlcalc_word_div_16
dw 0
==== test5.asm ====
Place a label as an equate with a dollar sign calculation. NASM emits them in the order the labels are defined in the source (add first, then div) despite the label defined later pointing at an address that's earlier.
section code
times 4 dw 1234h
wlcalc_word_add_15:
wlcalc_word_div_16: equ $ - 2
global wlcalc_word_add_15
global wlcalc_word_div_16
dw 100h
==== test6.asm ====
A ''jmp far'' with a destination label in the same segment.
section DOSSECTION
label:
times 4 dw 0
wlcalc_word_add_15:
wlcalc_word_div_16: equ $ - 2
global wlcalc_word_add_15
global wlcalc_word_div_16
dw 0
jmp far label
==== test7.asm ====
An ''extern'' label written to a word in the section.
section DOSSECTION
extern label
dw label
==== test8.asm ====
Attempt to cause a common variable overflow.
section DOSSECTION
common variable 4999999999:1024
==== test9.asm ====
A wlcalc label as an equate, pointing to the same word as a non-equate wlcalc label.
section code
times 4 dw 1234h
wlcalc_word_add_15:
dw 2642h
wlcalc_word_div_16: equ $ - 2
global wlcalc_word_add_15
global wlcalc_word_div_16
dw 100h
==== test10.asm ====
Multiple wlcalc requests with differing sizes and trailing identifiers.
section code
wlcalc_word_shr_4?bar:
global wlcalc_word_shr_4?bar:
dw 123h
nop
wlcalc_byte_shr_4?foo:
global wlcalc_byte_shr_4?foo:
dw 123h
nop
wlcalc_3byte_shr_4?foo:
global wlcalc_3byte_shr_4?foo:
dd 0FF123456h
wlcalc_dword_shr_4?foo:
global wlcalc_dword_shr_4?foo:
dd 12345678h
int3
==== test11.asm ====
A wlcalc request with the divisor as zero.
section code
global wlcalc_word_div_0
wlcalc_word_div_0:
dw 1
==== test12.asm ====
A wlcalc request with a "subr" operation, to negate a label.
section code
wlcalc_word_subr_0:
global wlcalc_word_subr_0:
dd label
times 16 nop
label:
==== test13.asm ====
A wlcalc request that will encounter a short read at the executable's EOF.
section code
wlcalc_word_subr_0:
global wlcalc_word_subr_0:
==== test14.asm ====
A wlemitalign test case.
section code
times 4 db 0
section WLEMITALIGNdata align=16
==== test15.asm ====
Multiple new wlcalc requests: OR, MUL, XOR, and AND.
section code
wlcalc_word_or_4?bar:
global wlcalc_word_or_4?bar
dw 1000h
nop
wlcalc_word_mul_256?foo:
global wlcalc_word_mul_256?foo
dw 26h
nop
wlcalc_word_xor_4096?bar:
global wlcalc_word_xor_4096?bar
dw 1000h
nop
wlcalc_word_and_4096?bar:
global wlcalc_word_and_4096?bar
dw 1010h
nop
==== test16.asm ====
A dword MUL wlcalc request that overflows the variable.
section code
wlcalc_dword_mul_256?foo:
global wlcalc_dword_mul_256?foo
dd 11223344h
nop
==== test17.asm ====
A CLR wlcalc request.
section code
wlcalc_dword_clr_256?foo:
global wlcalc_dword_clr_256?foo
dd -1
nop
==== test18.asm ====
A wlcalc request with a literal >= 64 KiB, and as a hexadecimal number.
section code
wlcalc_dword_clr_0x10000?foo:
global wlcalc_dword_clr_0x10000?foo
dd -1
nop
==== test19.asm ====
Multiple wlcalc requests: Hexadecimal, decimal, binary, all with underscore separators within the numbers.
section code
wlcalc_dword_clr_0xFF_FF?foo:
global wlcalc_dword_clr_0xFF_FF?foo
dd -1
nop
wlcalc_dword_clr_65_535?foo:
global wlcalc_dword_clr_65_535?foo
dd -1
nop
wlcalc_dword_clr_1111_0000B?foo:
global wlcalc_dword_clr_1111_0000B?foo
dd -1
nop
==== test20.asm ====
A wlcalc request with a constant that overflows the 4 Gi - 1 numeric range.
section code
wlcalc_dword_clr_1_0000_0000h?foo:
global wlcalc_dword_clr_1_0000_0000h?foo
dd -1
nop
==== test21.asm ====
The wlcalc helper mmacro for NASM. Several tests of 32-bit constants.
%imacro wlcalc 1-2.nolist
global wlcalc_%1
wlcalc_%1: %2
%endmacro
section code
wlcalc dword_mul_01020304h
dd 8
wlcalc 3byte_xor_11223344h
dd 0F0F0F0Fh
wlcalc dword_div_1230000h
dd 1230_0000h
==== test22.asm ====
Repetition of a wlcalc request, and using the wlcalc mmacro with an equate.
%imacro wlcalc 1-2.nolist
global wlcalc_%1
wlcalc_%1: %2
%endmacro
section code
start:
wlcalc dword_mul_01020304h
dd 8
wlcalc 3byte_xor_11223344h
dd 0F0F0F0Fh
wlcalc dword_div_1230000h
dd 1230_0000h
%assign AMOUNT ($-$$) / 4
wlcalc dword_xor_FF00FF00h_repeat_%[AMOUNT], equ start
==== test23.asm ====
Like prior example but with additional wlcalc requests in pass 1 and pass 2, to test that the passes are honoured.
%imacro wlcalc 1-2.nolist
global wlcalc_%1
wlcalc_%1: %2
%endmacro
section code
start:
wlcalc dword_mul_01020304h
dd 8
wlcalc 3byte_xor_11223344h
wlcalc dword_and_0_pass_1
wlcalc word_or_2642h_repeat_2_pass_2
dd 0F0F0F0Fh
wlcalc dword_div_1230000h
dd 1230_0000h
%assign AMOUNT ($-$$) / 4
wlcalc dword_xor_FF00FF00h_repeat_%[AMOUNT], equ start
==== test24.asm ====
The wlcalc "seg" operation.
%imacro wlcalc 1-2.nolist
global wlcalc_%1
wlcalc_%1: %2
%endmacro
section code
start:
wlcalc word_seg_data?foo
dw 26h
wlcalc word_seg_data?bar
dw 0
wlcalc word_seg_stack?foo
dw 0
dw 0
times 16 nop
section data
align 16
times 16 nop
section stack stack
alignb 16
resb 512
==== test25.asm ====
A wlcalc "seg" operation with an unknown segment name.
%imacro wlcalc 1-2.nolist
global wlcalc_%1
wlcalc_%1: %2
%endmacro
section code
start:
wlcalc word_seg_data?foo
dw 26h
wlcalc word_seg_unknown?foo
dw 0
times 16 nop
section data
align 16
==== test26.asm ====
Another "seg" operation. Unclear why this.
%imacro wlcalc 1-2.nolist
global wlcalc_%1
wlcalc_%1: %2
%endmacro
section code
start:
wlcalc word_seg_data?foo
dw 26h
dw 0
times 16 nop
section data
align 16
==== test27.asm ====
A wlcalc "seg" operation with a dword variable. This is rejected by the linker.
%imacro wlcalc 1-2.nolist
global wlcalc_%1
wlcalc_%1: %2
%endmacro
section code
start:
wlcalc word_seg_data?foo
dw 26h
wlcalc word_seg_data
dw 26h
wlcalc dword_seg_data?foo
dw 0
times 16 nop
section data
align 16
==== test28.asm ====
A wlcalc "seg" request at offset 0FFFFh, which is rejected as an overflow.
%imacro wlcalc 1-2.nolist
global wlcalc_%1
wlcalc_%1: %2
%endmacro
section code
start:
wlcalc word_seg_data?foo
dw 26h
wlcalc word_seg_data?bar
dw 0
wlcalc word_seg_stack?foo
dw 0
dw 0
times 16 nop
times (0xffff) - ($-$$) db 0
wlcalc word_seg_data?quux
section data
align 16
times 16 nop
section stack stack
alignb 16
resb 512
==== test29.asm ====
A wlcalc sequence involving first shifting right, then in another pass applying a segment relocation ("seg").
%imacro wlcalc 1-2.nolist
global wlcalc_%1
wlcalc_%1: %2
%endmacro
section code
start:
wlcalc word_shr_4
wlcalc word_pass_1_seg_stack
dw stack_top + 15
wlcalc word_seg_data?foo
dw 26h
wlcalc word_seg_data?bar
dw 0
wlcalc word_seg_stack?foo
dw 0
dw 0
times 16 nop
section data
align 16
times 16 nop
section stack stack
alignb 16
resb 512
stack_top:
==== test30.asm ====
Testing the "segrel" and "minussegrel" wlcalc operations.
%imacro wlcalc 1-2.nolist
global wlcalc_%1
wlcalc_%1: %2
%endmacro
section code
start:
wlcalc word_shr_4
wlcalc word_pass_1_segrel_stack
dw stack_top + 15
wlcalc word_segrel_data?foo
dw 26h
wlcalc word_segrel_data?bar
dw 0
wlcalc word_segrel_stack?foo
dw 0
wlcalc word_minussegrel_data?bar
dw 100h
wlcalc word_minussegrel_stack?foo
dw 100h
dw 0
times 16 nop
section data
align 16
times 16 nop
section stack stack
alignb 16
resb 512
stack_top:
==== test31.asm ====
Reference to a label in another section, and making the label global.
section code
dw 1234h + label
section data
times 260h nop
global label
label:
==== test32.asm ====
The first wllist mmacro, and naive draft of two wllist list items. These are invalid to the eventual wllist implementation because the lists aren't declared and the items are missing the "L" key letter to indicate the list name.
%imacro wllist 1.nolist
global ..@wllist_%1?%[%%l]
..@wllist_%1?%[%%l]:
%endmacro
section code
nop
nop
global wllist_init_code_386
wllist_init_code_386:
dd "Quux"
wllist init_code_386
db 26h
section init align=1
==== test33.asm ====
Multiple wllist list declarations, in the "init" and "exit" segments. A wllist declaration of a group, "initgroup", that contains the "init" segment.
%imacro wllist 1.nolist
global ..@wllist_%1?%[%%l]
..@wllist_%1?%[%%l]:
%endmacro
section code
wllist n_sinit_linit_code_386
wllist n_sexit_lexit_code_386
wllist n_sexit_lexit_code_no386
wllist n_sinit_linit_code_no386
wllist g_ginitgroup_sinit
nop
nop
global wllist_linit_code_386
wllist_linit_code_386:
dd "Quux"
wllist linit_code_386
db 26h
group initgroup init
section init align=1
==== test34.asm ====
Similar to prior, but put the group declaration before the new list declarations. (This still works because of how the declarations are handled.)
%imacro wllist 1.nolist
global ..@wllist_%1?%[%%l]
..@wllist_%1?%[%%l]:
%endmacro
section code
wllist g_ginitgroup_sinit
wllist n_sinit_linit_code_386
wllist n_sexit_lexit_code_386
wllist n_sexit_lexit_code_no386
wllist n_sinit_linit_code_no386
nop
nop
global wllist_linit_code_386
wllist_linit_code_386:
dd "Quux"
wllist linit_code_386
db 26h
group initgroup init
section init align=1
==== test35.asm ====
A wllist group declaration that includes an unknown section name, "omit".
%imacro wllist 1.nolist
global ..@wllist_%1?%[%%l]
..@wllist_%1?%[%%l]:
%endmacro
section code
wllist g_ginitgroup_somit
wllist n_sinit_linit_code_386
wllist n_sexit_lexit_code_386
wllist n_sexit_lexit_code_no386
wllist n_sinit_linit_code_no386
nop
nop
global wllist_linit_code_386
wllist_linit_code_386:
dd "Quux"
wllist linit_code_386
db 26h
group initgroup init
section init align=1
==== test36.asm ====
Multiple group declarations, one of them containing multiple segments.
%imacro wllist 1.nolist
global ..@wllist_%1?%[%%l]
..@wllist_%1?%[%%l]:
%endmacro
section code
wllist g_gexitgroup_sexit
wllist g_ginitgroup_sinit_stest
wllist n_sinit_linit_code_386
wllist n_sexit_lexit_code_386
wllist n_sexit_lexit_code_no386
wllist n_sinit_linit_code_no386
wllist n_stest_ltest
nop
nop
global wllist_linit_code_386
wllist_linit_code_386:
dd "Quux"
wllist linit_code_386
db 26h
group initgroup init
section init align=1
==== test37.asm ====
Entering a large number of entries into the "init_code_no386" list.
%imacro wllist 1.nolist
global ..@wllist_%1?%[%%l]
..@wllist_%1?%[%%l]:
%endmacro
section code
wllist g_gexitgroup_sexit
wllist g_ginitgroup_sinit_stest
wllist n_sinit_linit_code_386
wllist n_sexit_lexit_code_386
wllist n_sexit_lexit_code_no386
wllist n_sinit_linit_code_no386
wllist n_stest_ltest
nop
nop
global wllist_linit_code_386
wllist_linit_code_386:
dd "Quux"
wllist linit_code_386
db 26h
%rep 100
wllist linit_code_no386
nop
%endrep
group initgroup init
section init align=1
==== test38.asm ====
This test creates a small test program that patches part of its code. It uses the symbols generated as PUBDEF records in the wllist object file, and also checks that the list amount and list end symbols match one another. The wllist mmacro accepts a second parameter to use it as an equate.
%imacro wllist 1-2.nolist
global ..@wllist_%1?%[%%l]
..@wllist_%1?%[%%l]: %2
%endmacro
section code
wllist g_ginitgroup_sinit
wllist n_sinit_linit_code_386
wllist n_sinit_linit_code_no386
mov ax, init
mov ds, ax
extern init_code_386
extern init_code_386.end
extern init_code_386.amount
extern init_code_no386
extern init_code_no386.end
extern init_code_no386.amount
mov si, init_code_386
mov cx, init_code_386.amount
l:
lodsw
loop l
cmp si, init_code_386.end
jne error
mov si, init_code_no386
mov cx, init_code_no386.amount
q:
lodsw
xchg di, ax
mov byte [cs:di], 90h
loop q
cmp si, init_code_no386.end
jne error
align 64
nop
nop
wllist linit_code_386
mov ax, 1234h
nop
wllist linit_code_386
inc ax
wllist linit_code_no386
o32
push ax
wllist linit_code_no386
o32
push bx
wllist linit_code_no386
o32
push cx
wllist linit_code_no386
o32
push dx
mov al, '^'
wllist linit_code_no386, equ $ - 1
mov ax, 4C00h
int 21h
error:
mov ax, 4CFFh
int 21h
group initgroup init
section init align=1
==== test39.asm ====
Based on prior. Additionally, test the wllist repetition and repetition step width features. Also test that zero repetition and different bases for the repetition count work.
%imacro wllist 1-2.nolist
global ..@wllist_%1?%[%%l]
..@wllist_%1?%[%%l]: %2
%endmacro
section code
wllist g_ginitgroup_sinit
wllist n_sinit_linit_code_386
wllist n_sinit_linit_code_no386
wllist n_sinit_lemptylist
mov ax, init
mov ds, ax
extern init_code_386
extern init_code_386.end
extern init_code_386.amount
extern init_code_no386
extern init_code_no386.end
extern init_code_no386.amount
mov si, init_code_386
mov cx, init_code_386.amount
l:
lodsw
loop l
cmp si, init_code_386.end
jne error
mov si, init_code_no386
mov cx, init_code_no386.amount
q:
lodsw
xchg di, ax
mov byte [cs:di], 90h
loop q
cmp si, init_code_no386.end
jne error
align 64
nop
nop
wllist linit_code_386
mov ax, 1234h
nop
wllist linit_code_386
inc ax
wllist linit_code_no386
o32
push ax
wllist linit_code_no386
o32
push bx
wllist linit_code_no386
o32
push cx
wllist linit_code_no386
o32
push dx
wllist r4_w2_linit_code_no386
pop edx
pop ecx
pop ebx
pop eax
xor bx, bx
wllist r3_linit_code_no386
mov bx, 2642h
wllist r0_linit_code_no386
wllist r0x0_linit_code_no386
wllist r0h_linit_code_no386
wllist r0_0_0b_linit_code_no386
mov al, '^'
wllist linit_code_no386, equ $ - 1
wllist r0_w26h_lemptylist
mov ax, 4C00h
int 21h
error:
mov ax, 4CFFh
int 21h
group initgroup init
section init align=1
{{tag>warplink testspam}}
~~DISCUSSION~~