x86 NASM程序集 - 堆栈问题

时间:2011-11-04 00:21:46

标签: assembly input x86 nasm

我正在制作一个程序,只需简单地接受用户输入两次,然后将结果打印到标准输出中。我遇到的问题是,当从输入中断(在 eax 中)返回结果时,我将它推入堆栈以供以后使用。我再次为第二个用户输入执行此操作。

我到目前为止的代码是:

%include "system.inc" ; used for renaming of interrupts (sys.write and sys.read)

section .data
    greet:      db 'Hello!', 0Ah, 'What is your name?', 0Ah
    greetL:     equ $-greet     ;length of string
    colorQ:     db 'What is your favorite color?', 0Ah
    colorL:     equ $-colorQ 
    suprise1:   db 'No way '
    suprise1L:  equ 7
    comma:      db ', '
    commaL:     equ $-comma
    suprise3:   db ' is my favorite color, too!', 0Ah
    suprise3L:  equ $-suprise3


section .bss

name: resb 50
color: resb 50

section .text

    global _start
_start:


greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

    xor ecx, ecx
    mov eax, ecx
    push ecx

askcolor:
    mov eax, 4
    mov ebx, 1
    mov ecx, colorQ
    mov edx, colorL
    sys.write

getcolor:
    mov eax, 3
    mov ebx, 0
    mov ecx, color
    mov edx, 50
    sys.read

    xor ebx, ebx
    mov ebx, eax
    push ebx


thesuprise:
    mov eax, 4
    mov ebx, 1
    mov ecx, suprise1
    mov edx, suprise1L
    sys.write

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx    
    pop ecx
    sub ecx, 1
    mov edx, ecx

    mov eax, 4
    mov ebx, 1
    mov ecx, name
    mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, comma
    mov edx, commaL
    sys.write

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx
    pop ebx
    sub ebx, 1
    mov edx, ebx

    mov eax, 4
    mov ebx, 1
    mov ecx, color
    mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, suprise3
    mov edx, suprise3L
    sys.write

done:

    mov eax, 1  
    mov ebx, 0  
    sys.exit

我在输出中出现严重的间距问题,很可能是因为当我按下/弹出它时我如何处理 eax 中返回的值。有没有办法解决这个问题/我做错了吗?

2 个答案:

答案 0 :(得分:1)

greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

我不知道这些sys.writesys.read宏应该为您做什么,但是在调用系统调用之前,他们可能会使用正确的值加载eax int 0x80,所以你可能不需要自己做。否则他们没有多大意义......

(但这不是问题; 43分别是32位Linux x86上writeread的正确系统调用号。)

实际问题可能在这里:

    xor ecx, ecx
    mov eax, ecx
    push ecx

这看起来是错误的:您将自己与ecx进行异或运算,将其设置为零。然后,您将ecx(现在为0)分配给eax(这是系统调用的结果),因此系统调用的结果将被丢弃。然后你将ecx(仍为0)推到堆栈上。

更进一步,你有:

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx    
    pop ecx
    sub ecx, 1
    mov edx, ecx

...这也很奇怪:当你要从其他地方重新加载它们时,为什么归零ecxedx以及xor指令?


我猜你可能只有mov的操作数错误。而不是:

    xor ecx, ecx
    mov eax, ecx
    push ecx

......如果你说:

    xor ecx, ecx
    mov ecx, eax
    push ecx

....你至少会成功地将eax中的值(来自系统调用的返回代码)推送到堆栈上,尽管说起来会简单得多:

    push eax

最后:你问“名字”问题,并且(假设上面已修复)将结果长度推到堆栈上。然后你问“颜色”问题,并将结果长度推到堆栈上。

然后你打印“名字”惊喜,使用从堆栈中弹出的第一个值,这是你从“颜色”问题中保存的长度。 (堆叠是先进先出!)然后使用“名称”问题的长度打印“颜色”惊喜。

答案 1 :(得分:0)

感谢Matt和ott。

以下是解决方案:

%include "system.inc"

section .data
    greet:      db 'Hello!', 0Ah, 'What is your name?', 0Ah
    greetL:     equ $-greet     ;length of string
    colorQ:     db 'What is your favorite color?', 0Ah
    colorL:     equ $-colorQ 
    suprise1:   db 'No way '
    suprise1L:  equ 7
    comma:      db ', '
    commaL:     equ $-comma
    suprise3:   db ' is my favorite color, too!', 0Ah
    suprise3L:  equ $-suprise3


section .bss

name: resb 50
color: resb 50

section .text

    global _start
_start:


greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

    sub eax, 1
    push eax

askcolor:
    mov eax, 4
    mov ebx, 1
    mov ecx, colorQ
    mov edx, colorL
    sys.write

getcolor:
    mov eax, 3
    mov ebx, 0
    mov ecx, color
    mov edx, 50
    sys.read

    sub eax, 1
    push eax


thesuprise:
    mov eax, 4
    mov ebx, 1
    mov ecx, suprise1
    mov edx, suprise1L
    sys.write

    xor eax, eax
    pop eax
    mov ecx, eax
    pop eax
    mov edx, eax
    push ecx

    mov eax, 4
    mov ebx, 1
    mov ecx, name
    ;mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, comma
    mov edx, commaL
    sys.write

    xor eax, eax
    pop eax
    mov edx, eax

    mov eax, 4
    mov ebx, 1
    mov ecx, color
    ;mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, suprise3
    mov edx, suprise3L
    sys.write

done:

    mov eax, 1  
    mov ebx, 0  
    sys.exit