assembly - Weird Macros (TASM) -
consider following macros:
pixelfast macro ; macro draws pixel, assuming coordinates loaded in cx&dx , color in al. xor bh, bh mov ah, 0ch int 10h endm drawrect macro x1, y1, x2, y2, color local @@loop, @@row_loop xor cx, cx mov dx, y1 mov al, byte ptr [color] @@loop: mov cx, x1 @@row_loop: pixelfast inc cx cmp cx, x2 jna @@row_loop inc dx cmp dx, y2 jna @@loop endm rendtoolbar macro drawrect colordisp_x1, colordisp_y1, colordisp_x2, colordisp_y2, foreground_color mov temp_color, 36h drawrect colorbtn1_x1, colorbtn1_y1, colorbtn1_x2, colorbtn1_y2, temp_color mov temp_color, 2eh drawrect colorbtn2_x1, colorbtn2_y1, colorbtn2_x2, colorbtn2_y2, temp_color mov temp_color, 4h drawrect colorbtn3_x1, colorbtn3_y1, colorbtn3_x2, colorbtn3_y2, temp_color mov temp_color, 2bh drawrect colorbtn4_x1, colorbtn4_y1, colorbtn4_x2, colorbtn4_y2, temp_color endm
somewhere in code, use rendtoolbar macro. supposed draw big white canvas, , small square , next smaller squares in pattern, irrelevant question. notice rendtoolbar calls drawrect 5 times. followed code in turbo debugger (because went awfully wrong) , noticed in 4th execution of drawrect macro, "int 10h" pixelfast not "int 10h", rather "int 2". causes nmi, messes stuff program. want know makes tasm expand macro differently line in 4th call macro, despite fact line "int 10h" not rely on macro arguments. if @ image, can see unexpected "int 2" there, supposed "int 10". after it, can see:
cmp [bx+si], ax add ch, bh cmp [bx+03], dx
according macro's source code, these 3 instructions in fact supposed be
inc cx cmp cx, colorbtn3_x2 jna @@row_loop
there other instructions bit off before interrupt, point.
consider math transform logical (segment:offset) addresses linear ones:
cs:ip = 49ae:03cc = 49eac
3cc offset of first unexpected byte.
ss:sp = 39ed:fffc = 49ecc
.
visualizing 2 linear addresses, have
| | | 49ecc | <-- stack pointer, going down | | 32 bytes below | | | 49eac | <-- execution flow, going | |
your stack must have clashed code segment @ point before screenshot.
try setting stack far enough code.
the maximum stack size in real mode 64kib, size of segment.
in dos safe assume memory after program not used1 and, long exists, can use stack. not wasting memory dos not multitasking.
note stack segment won't take space on binary file unless explicitly define things in it.
there 2 ways manage stack:
using assembler
see tasm manual reference, page 92.if using
stack
directive put upper bound on estimated size of stack.if writing exe can use model modifier
farstack
.
ss:sp
should set based on values linker wrote on mz header.
let have full 64kib stack not putting stack segment dgroup.manually
if know won't need full 64kib of stack, can put @ end of data segment (that com code segment);com ;exe mov ax, cs mov ax, ds ;assume small memory model mov ss, ax mov ss, ax ;see below xor sp, sp xor sp, sp
this gives 64kib - <code+data size>.
if need full 64kib stack can use next available segment
;com ;exe mov ax, cs mov ax, ds ;assume small memory model, if not add ax, 1000h add ax, 1000h ;use symbol last data mov ss, ax mov ss, ax ;segment xor sp, sp xor sp, sp
this assumes last segment if used saves segment/offset/symbols arithmetic.
1 because dos not multitasking , programs loaded above tsr programs.
non resident part of command.com loaded top of conventional memory can overwritten.
Comments
Post a Comment