Я пытаюсь создать программу, которая принимает некоторые входные данные, находит странные позиции в строке и печатает соответствующий символ, поэтому вы вводите 'somewords', а она печатает 'oeod'.
В итоге я сделал цикл, который выполняет итерациизатем строка делит счетчик на 2 и печатает символ в позиции счетчика, если остаток не равен 0.
Вместо одного символа он ничего не печатает.
Полный код:
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
Я безуспешно пытался использовать bl, al и cl.Я также попытался сделать некоторые проверки.Например, выведите счетчик в .iterstring:
nasm -f elf lr3.asm && ld -m elf_i386 lr3.o -o lr3 && ./lr3
Enter the string: test
1
2
3
4
5
Таким образом, похоже, что итерация работает нормально.
Больше всего мне повезло с ответом на аналогичный вопрос ( Как напечатать символ в Linux x86 NASM? ) с такими изменениями в коде:
.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
Теперь все работает как задумано:
nasm -f elf lr3.asm && ld -m elf_i386 lr3.o -o lr3 && ./lr3
Enter the string: somewords
oeod
Мне пришлось убрать больше инструкций push-pop, а также пришлось переместить счетчик в esi, потому что регистры не нажималисьвсегда восстанавливал их значение в стеке, что странно для меня.
Когда я пытался перейти на ecx-адрес byte [eax+ecx]
, это работало, но когда я менял его на byte [eax+1]
, это вызывало segfault, потому что восстановление eax после popперерыв.Когда я нажал ecx, чтобы распечатать сообщение, а затем снова отправил его обратно, это привело к segfault, и gdb показал, что внутри ecx был мусорный код после извлечения.
С текущим кодом все работает нормально.