代码编译得很好[NASM
]
但是,只要我输入第一个值,它就会崩溃
我不知道什么是错的,目标是输入一个字符串并输出字符串的反向,所有这些都在循环中重复,如果用户说是('Y'或'y')
**.DATA
; Initialized Data Definitions
strlength EQU 40
PromptStr dd "Please input a string (must be less than 40 characters long): ", 0
OutputStr dd "The reverse string is: ", 0
AgainStr dd "Would you like ot try again? ('Y' or 'y' for yes): ", 0
.UDATA
; Uninitialized Data Definitions
string resb strlength
.CODE
; Program Code
.STARTUP
nwln ; start output at a new line
PutStr PromptStr
nwln
while:
GetStr string
mov EBX, string
loop_in:
push dword[EBX]
add EBX, 4
cmp dword[EBX], 0
jnz loop_in
loop_out:
XOR EBX, EBX
pop EBX
PutCh [EBX]
cmp dword[EBX], 0
jnz loop_out
nwln
PutStr AgainStr
GetStr EBX
mov AL, [EBX]
cmp AL, 'Y'
jz while
cmp AL, 'y'
jz while
Pause
.EXIT**
我将第一个循环更改为
loop_in:
mov AL, [EBX]
push byte[AL]
add EBX, 4
cmp byte[AL], 0
jnz loop_in
并且我得到此错误“错误:无效的有效地址”
当我改为“byte”
时loop_in:
push byte[EBX]
add EBX, 4
cmp byte[EBX], 0
jnz loop_in
我得到“错误:操作码和操作数的无效组合”
代表行{add EBX,4}
所以我改变了
loop_in:
push EBX
inc EBX
cmp byte[EBX], 0
jnz loop_in
loop_out:
XOR EBX, EBX
pop EBX
PutCh [EBX]
cmp byte[EBX], 0
jnz loop_out
现在它编译了,我到目前为止
Please input a string (must be less than 40 characters long):
asdf
fdsaêë
崩溃到Windows之前
答案 0 :(得分:0)
也许这样的事情可行:
loop_in:
mov AX, [EBX]
push AX ; move two characters to the stack
inc EBX
inc EBX
cmp AX, 0
jnz loop_in
cmp AL, 0
jnz loop_in ; two end-of-string checks,
; because we push two characters
loop_out:
pop AX
PutCh AH
PutCh AL
dec EBX
dec EBX
cmp EBX, string
ja loop_out
答案 1 :(得分:0)
你是如何“编译”这个,因为我们不编译汇编源代码,我们汇编并可选择链接。
我没有你的宏文件,所以在这里我使用了C库中的一些函数,但它们都应该是相同的:
push dword [stdin]
push MAX_INPUT
push string
call fgets
add esp, 4 * 3
;~ fgets adds the NL char to string, replace with NULL
push string
call RemoveNL
mov esi, string
xor ebx, ebx
PushChar:
movzx eax, byte[esi + ebx]
test eax, eax
jz PopChar
push eax
inc ebx
jmp PushChar
PopChar:
push fmtchar
push dword [stdout]
call fprintf
add esp, 4 * 3
dec ebx
jnz PopChar
jmp Done
RemoveNL:
mov esi, [esp + 4]
xor ecx, ecx
dec ecx
.FindNL:
inc ecx
cmp byte [esi + ecx], 10
jne .FindNL
mov byte [esi + ecx], 0
ret 4
现在解释一下:
mov esi, string
xor ebx, ebx
PushChar:
movzx eax, byte[esi + ebx]
test eax, eax
jz PopChar
push eax
inc ebx
jmp PushChar
一旦你拨打任何你打电话来获取输入,字符串就包含字符。我们将string
的地址移动到esi
,将ebx
清零,以用作字符数组的索引。
首先,我们从esi + ebx中的指针移动一个字节并将其移动到eax
零扩展eax
,当我们在它时,它将char的ASCII值移动到eax的低字节,并且将未使用的上部字节清零。然后我们查找带有NULL
的{{1}}终结符,如果它在当前索引处为零,我们就完成了将值推送到堆栈上。如果value不为0,我们将test
推入堆栈并将eax
(我们的索引)递增1并继续循环。
ebx
不需要PopChar:
push fmtchar
push dword [stdout]
call fprintf
add esp, 4 * 3
dec ebx
jnz PopChar
一个值,然后pop
它再次作为我们的print函数/宏的参数,因为它已经在堆栈上并且堆栈是LIFO,推送的最后一个字符是准备打印。在这里,您只看到为push
推送的2个参数,但我调整了esp,好像我按了3个参数。好吧,我们从堆栈中删除打印的字符,然后准备好下一个字符。我们怎么知道何时停止?我们使用fprintf
循环中的ebx
中的数字,并将该值减小到0。
输出: