程序在奇怪的情况下崩溃

Program crashes under weird condition

我是汇编的新手,我有一个奇怪的错误。我使用 286 和 TASM 汇编器。我在 dosbox 上模拟我的程序。我的程序只是要求用户输入一个字符串,然后它会输出相同的字符串。这是我的全部代码:

.286
.model huge
.stack 300h

.CODE
start:


lea bx, x
push bx
call gets   ; Read the string
lea bx, x
push bx
call puts   ; Output the string

jmp terminate   ; End it

; ---------- char getche(void) ----------

getche:
; Reads a character from keyboard and output into dl register

push ax     ; push stacks we use

mov ah, 1h  ; get character and echo
int 21h
mov dl, al  ; output the character into dl

pop ax      ; pop  the stacks

ret     ; return

; ---------- end of function ----------

; ---------- void putch(char c) ----------

putch:
; Print character into screen

push ax     ;Push the stacks we use
push bx
push dx
push bp

mov bp, sp  ; Load the character
mov bx, [bp+10]

mov dl, [bx]    ; store the argument into dx
mov ah, 2h  ; print the character
int 21h

pop bp      ; Pop all the stacks we used
pop dx
pop bx
pop ax

ret 2       ; return

; ---------- end of function ----------

; ---------- void puts(char *p) ----------

puts:
; Prints string to the console

push bp     ; Push the stacks
push bx
push cx

mov cl, 0   ; The null character
mov bp, sp

mov bx, [bp+8]  ; Load the adress of beginning of the string

.pts_loop:
cmp [bx], cl
jz .pts_exit    ; Jump if it is the null character

push bx
call putch  ; Print the character
inc bx
jmp .pts_loop

.pts_exit:
pop cx      ; Pop the stacks
pop bx
pop bp

ret 2

; ---------- end of function ----------

; ---------- void gets(char *p) ----------

gets:
; Reads a string from keyboard

push bp ; Push stacks
push bx
push cx

mov bp, sp ; Load the address
mov bx, [bp+8]
mov cl, 13

.gts_loop:
call getche
mov [bx], dl
inc bx
cmp dl, cl ; Check if it is the 'Enter' key
jnz SHORT .gts_loop

mov [bx], 0 ; Add the null

pop cx      ; Pop stacks
pop bx
pop bp

ret 2


; ---------- end of function ----------

terminate:
mov ah, 4ch     ; terminate the program
mov al, 00
int 21h

.DATA

x db "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ; Doesn't matter what's inside

END start

如果我的字符串的长度 <= 10。它将毫无问题地终止。但是,如果它 > 10 则它会崩溃。我使用了调试,我注意到在执行过程中一切正常运行,直到它终止。当我执行中断时,它会在全为 0 的地方跳转并永远运行……我猜我的字符串可能会覆盖一些重要数据。我试图将 .DATA 从我的代码开头移动到结尾,但它没有多大帮助。有什么建议吗?

编辑:我将 mov cl, 13 更改为 mov cl, 0。我将堆栈增加到 200h 甚至 300h 但仍然是同样的问题。

您从未设置 DS/ES。

mov ax,.DATA  ; <-- Syntax used depends on assembler used!!!
mov ds,ax
mov es,ax

或者完全删除 .DATA 指令。这会将字符串 x 放入 .CODE 部分,所以这次设置 DS/ES 代码如

start:
 mov ax,cs
 mov ds,ax
 mov es,ax

当处理超过 10 个字符时,问题首先从 DOS 函数 4Ch 开始,这是因为在 ProgramSegmentPrefix DOS 的偏移量 10 处保留了一些非常重要的中断向量。这些被不初始化 DS 覆盖。当 EXE 启动时,DS 寄存器指向 PSP。

您忘记初始化DS:

...
.CODE
start:
mov ax, @data
mov ds, ax
...

对于 MS-DOS 程序,您必须初始化 DS 总是!

我测试了它,现在你的代码对我有用。

顺便说一句:

.model huge如无特殊原因,请避开!使用 .model small.

改变

mov [bx], 0 ; Add the null ; *Warning* Argument needs type override

mov byte ptr [bx], 0 ; Add the null