8086 汇编程序总是打印相同的字符串

8086 assembly program always prints the same string

我使用启用了 fasm 语法的 emu8086 编写了以下程序。如您所见,程序应该第一次打印 "Overflow flag not set" ,然后在添加设置溢出标志后,它应该打印 "Overflow flag not set."

然而,事实并非如此。在任何情况下,该程序都会打印 "overflow flag set"。我已经逐步执行了这段代码,o_set 位于地址 0,o_notset 位于地址 13h。 无论在调用 int 21h 和 al 09h 时将 13h 还是 0h 放入 dx,它都会打印 "overflow flag set." 我在这里很困惑,因为我确实分配了它们作为数据段中的两个独立区域。请注意,跳转逻辑似乎工作正常,问题是无论在 dx 中放置什么,总是打印相同的消息。事实上,如果我在 dx 中放入一个 99,它仍然会打印 "overflow flag set."

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

我已经评论了错误和需要修复的地方:

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。因为您没有这样做,所以您的字符串是从错误的位置打印的。

我在您的字符串中添加了回车符 return 和换行符,以便它们打印在不同的行上。

您的代码不能依赖程序启动时清除的溢出标志。您需要使用将清除它的指令。 test ax, ax 如果您不介意它改变其他标志,就可以解决问题。

您的一个 jo 指令中存在一个错误,当检测到溢出时它转到了错误的标签。