我使用启用了fasm语法的emu8086编写了以下程序。正如您所看到的,程序应该在第一次打印“溢出标志未设置”,然后在添加设置溢出标志之后,应该打印“溢出标志未设置”。
但是,这不是正在发生的事情。该程序在任何情况下都会打印“溢出标志设置”。我已经完成了这个代码,o_set在地址0,o_notset在地址13h。 无论13h或0h是否在21h时被调到dx,调用al 09h,它会打印“溢出标志设置。”我在这里很困惑,因为我确实将它们分配为两个数据段中的单独区域。请注意,跳转逻辑似乎工作正常,问题是无论dx中放置了什么,始终会打印相同的消息。事实上,如果我在dx中放置一个99,它仍会打印“溢出标志设置。”
format MZ
entry code_seg:start
stack 256
segment data_seg
o_set db "Overflow flag set $"
o_notset db "Overflow flag not set $"
segment code_seg
start:
push bp
mov bp, sp
mov cl, 99
jo of_flag_set
push o_notset
call printf
add sp, 2
add cl, 98
jo of_flag_set
jmp endme
of_flag_set:
push o_notset
call printf
add sp, 2
endme:
mov sp, bp
pop bp
mov ah, 0h
int 20h
; Need to put offset to msg on stack prior to call. Stack cleaned up by callee
printf:
push bp
mov bp, sp
mov dx, [bp+4] ;cant pop the retn addr into dx
mov ah, 09h
int 21h
mov sp, bp
pop bp
ret
答案 0 :(得分:3)
我评论了错误并需要修复的事情:
format MZ
entry code_seg:start
stack 256
segment data_seg
; Add carriage reurn and line feed to ut output on seprate lines.
o_set db "Overflow flag set", 13, 10, "$"
o_notset db "Overflow flag not set", 13, 10, "$"
segment code_seg
start:
push bp
mov bp, sp
mov ax, data_seg ; We must set up the DS register by pointing
; at the segment with our data
mov ds, ax
test ax, ax ; Make sure overflow flag is cleared
; Not guaranteed when our program starts
mov cl, 99
jo of_flag_set ; You jumped to the wrong label when overflow was set
push o_notset
call printf
add sp, 2
add cl, 98
jo of_flag_set
jmp endme
of_flag_set:
push o_set
call printf
add sp, 2
endme:
mov sp, bp
pop bp
mov ah, 0h
int 20h
; Need to put offset to msg on stack prior to call. Stack cleaned up by callee
printf:
push bp
mov bp, sp
mov dx, [bp+4] ;cant pop the retn addr into dx
mov ah, 09h
int 21h
mov sp, bp
pop bp
ret
您的字符串没有正确打印(它们在屏幕上移动),因为您没有设置 DS (数据段)寄存器。创建DOS MZ(EXE)程序时,您需要明确地将数据区data_seg
的段位置移动到 DS 。因为你没有这样做,你的字符串是从错误的位置打印出来的。
我在字符串中添加了回车符和换行符,因此它们会在不同的行上打印。
您的代码不能依赖程序启动时清除的溢出标志。您需要使用清除它的指令。如果您不介意改变其他旗帜,test ax, ax
会做到这一点。
您的jo
指令中有一个错误,当检测到溢出时,它会转到错误的标签。