Assembly x86 NASM程序集-堆栈问题

Assembly x86 NASM程序集-堆栈问题,assembly,input,x86,nasm,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

我正在编写一个程序,只需接收用户输入两次,然后在以后将结果打印到标准输出。我遇到的问题是,当结果从输入中断(在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时如何处理返回的值。有没有办法解决这个问题/我做错了吗

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.write
sys.read
宏应该为您做些什么,但是它们很可能会在调用带有
int 0x80
的syscall之前加载带有正确值的
eax
,所以您可能不需要自己去做。否则就没什么意义了

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

实际问题可能在这里:

    xor ecx, ecx
    mov eax, ecx
    push ecx
这看起来是错误的:您将ecx自身设置为独占ORing
ecx
,这会将其设置为零。然后将
ecx
(现在为0)分配给
eax
(这是系统调用的结果),因此系统调用的结果将被丢弃。然后将
ecx
(仍然为0)推到堆栈上

更进一步,你有:

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx    
    pop ecx
    sub ecx, 1
    mov edx, ecx
…这也很奇怪:为什么要用
xor
指令将
ecx
edx
归零,而您只是想从其他地方重新加载它们,然后再加载两条指令


我猜你可能只是把
mov
的操作数弄错了。而不是:

    xor ecx, ecx
    mov eax, ecx
    push ecx
…如果你说:

    xor ecx, ecx
    mov ecx, eax
    push ecx
..您至少可以成功地将
eax
(系统调用的返回代码)中的值推送到堆栈上,尽管只说:

    push eax

最后:问“name”问题,并(假设上面的长度固定)将结果长度推到堆栈上。然后问“颜色”问题,并将结果长度推到堆栈上


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

多亏了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

宏只会使代码更具可读性;他们除了用一个不同的词替换int 80之外什么都不做。我还没读完,但它看起来像是个漂亮的帮手!好的,我明白你对所有评论的看法,但现在我只是修正了它们。你的猜测是正确的,我改了。我只是把一切都归零以防万一。我的问题是,我相信,更进一步。为什么当我弹出第一个输入字符串的长度时,两个输入都有问题(间距问题)?单词的一部分被切碎在第二个单词中,第一个单词在更新答案后有很大的空间。如果你按下一个值X,然后按下另一个值Y,弹出的第一个值将是Y(不是X)。我如何解决这个问题?弹出第一个值,弹出第二个值,然后将第一个值推回?这是一种方法。或者,您可以从
esp
以偏移量的形式访问堆栈的内容。或者您可以将值存储在其他地方,而不使用堆栈。