程序在奇怪的情况下崩溃
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
我是汇编的新手,我有一个奇怪的错误。我使用 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