我尝试制作一个程序,该程序需要一些输入,在字符串中找到奇数个位置并打印相应的字符,因此您输入“ somewords”并打印“ oeod”。
我最后做了一个循环,遍历字符串,然后将计数器除以2,如果余数不等于0,则将字符打印在计数器的位置。
它不会打印任何字符,而不是单个字符。
完整代码:
production.properties
我没有运气就尝试使用bl,al和cl。我也尝试做一些检查。例如,在.iterstring中打印计数器:
SECTION .bss
inp: resb 255
SECTION .data
msg db "Enter the string: ", 0h
SECTION .text
global _start
_start:
mov eax, msg
call stprint
mov edx, 255 ; take user input
mov ecx, inp
mov ebx, 0
mov eax, 3
int 80h
call findodd
mov ebx, 0
mov eax, 1
int 80h
findodd:
push eax
push ecx
push edx
push esi
push ebx
mov ecx, 0 ; counter
mov esi, 2 ; divider
.iterstring:
mov eax, inp ; move input to eax
cmp byte [eax+ecx], 0 ; check for end of the string in position
je .finish ; if equal, finish
inc ecx
push eax
mov eax, ecx ; move counter to eax
xor edx, edx ; divide it by 2
idiv esi
pop eax
cmp edx, 0 ; check the remainder
jnz .printchar ; print character if != 0
jmp .iterstring
.printchar:
push eax
push ebx
movzx ebx, byte [eax+ecx] ; move single byte to ebx
push ecx
mov ecx, ebx ; move ebx to print
mov edx, 1 ; print the character
mov ebx, 1
mov eax, 4
int 80h
pop ecx
pop eax
pop ebx
jmp .iterstring
.finish:
pop eax
pop ecx
pop edx
pop esi
pop ebx
ret
; print string function (taken from tutorial)
; if I try to print single character with it I get SEGFAULT
stprint:
push edx
push ecx
push ebx
push eax
call stlen
mov edx, eax
pop eax
mov ecx, eax
mov ebx, 1
mov eax, 4
int 80h
pop ebx
pop ecx
pop edx
ret
stlen:
push ebx
mov ebx, eax
nextch:
cmp byte [eax], 0
jz finish
inc eax
jmp nextch
finish:
sub eax, ebx
pop ebx
ret
所以看起来迭代工作正常。
对于类似的问题(How to print a character in Linux x86 NASM?),我最幸运的是对代码进行了以下更改:
nasm -f elf lr3.asm && ld -m elf_i386 lr3.o -o lr3 && ./lr3
Enter the string: test
1
2
3
4
5
但是它将打印除第一个字符外的所有内容:
.printchar:
push eax
push ebx
push esi
mov eax, inp
movzx ebx, byte [eax+ecx]
mov esi, ecx ; see below
push ecx
push ebx
mov ecx, esp
mov edx, 1 ; print the character
mov ebx, 1
mov eax, 4
int 80h
pop ecx
pop ebx
pop eax
pop ebx
mov ecx, esi ; without this it just prints 1 character and ends
pop esi ; so ecx is not restored with pop for some reason?
jmp .iterstring
我被困住了,无法得到我的错误。
修改,最终代码:
nasm -f elf lr3.asm && ld -m elf_i386 lr3.o -o lr3 && ./lr3
Enter the string: somewords
mewords
现在它可以正常工作了:
findodd:
push eax
push ecx
push edx
push esi
push ebx
mov esi, 0 ; counter
mov eax, inp
.iterstring:
inc esi
cmp byte [eax+esi], 0
jz .finish
test esi,1
jz .iterstring
movzx ecx, byte [eax+esi]
push ecx
mov ecx, esp
mov edx, 1
mov ebx, 1
push eax
mov eax, 4
int 80h
pop eax
pop ecx
jmp .iterstring
.finish:
pop eax
pop ecx
pop edx
pop esi
pop ebx
ret
我不得不删除更多的push-pop指令,还不得不将计数器移到esi中,因为先推送然后弹出寄存器并不总是将其值恢复到堆栈中,这对我来说很奇怪。
当我尝试移至nasm -f elf lr3.asm && ld -m elf_i386 lr3.o -o lr3 && ./lr3
Enter the string: somewords
oeod
的ecx地址时,它起作用了,但是当我将其更改为byte [eax+ecx]
时,它会出现段错误,因为在pop之后恢复eax会中断。当我推ecx打印一条消息然后将其弹出时,它最终出现了segfault,而gdb显示出ecx后,其中有垃圾代码。
使用当前代码,它可以正常工作。
答案 0 :(得分:3)
此行不正确:
mov ecx, ebx ; move ebx to print
write
(int 80h / eax=4
)期望ecx
包含要写入的数据的地址地址(请参见this table)。但是您要传递数据本身。
在修改后的代码中,您将字符放置在堆栈上,然后将其地址传递到ecx
中,因此是正确的。
但是,您到ecx
时已经增加了.printchar
。这就是为什么您的代码不会显示第一个字符的原因。
作为旁注,对偶数/奇数的检查不必要地复杂。可以简化为:
test ecx,1 ; set EFLAGS based on ecx AND 1
jnz .printchar