程序在奇怪的情况下崩溃

时间:2015-01-28 22:22:43

标签: assembly x86

我是装配新手,我有一个奇怪的错误。我使用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,但问题仍然存在。

2 个答案:

答案 0 :(得分:1)

您永远不会设置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。

答案 1 :(得分:1)

您忘记初始化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