Assembly x86 NASM程序集-堆栈问题
我正在编写一个程序,只需接收用户输入两次,然后在以后将结果打印到标准输出。我遇到的问题是,当结果从输入中断(在eax中)返回时,我将其推到堆栈上以供以后使用。对于第二个用户输入,我再次这样做 到目前为止,我掌握的代码是: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
%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自身设置为独占ORingecx
,这会将其设置为零。然后将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
以偏移量的形式访问堆栈的内容。或者您可以将值存储在其他地方,而不使用堆栈。