admin管理员组文章数量:1122832
I'm a beginner in assembly and I'm encountering unexpected behavior in my code. The code works as expected, printing numbers from contador
variable to 1, but when I removed the unused variable loops
(which is not used anywhere in the code), it started printing random numbers infinitely. I don't understand why this happens.
Here’s the relevant part of the code:
extern print
extern input
extern string_to_int
extern int_to_string
extern print_num
section .data
contador dq 30
loops dq 10
v4 db " ", 10
section .bss
atual resb 1
section .text
global main
main:
push rbp
mov rbp, rsp
print_loop:
mov rax, [contador] ; pass the address
call int_to_string
push rsi
push rdi
mov rdx, [rsi]
mov [atual], rdx
mov rdi, atual
call print_num
mov rdi, v4
call print
dec qword [contador]
cmp qword [contador], 0
jne print_loop
pop rdi
pop rsi
mov rsp, rbp
pop rbp
mov rax, 60
mov rdi, 0
syscall
Why does the code start printing random numbers infinitely when I remove the loops
variable? Also, I would appreciate any tips or references to help improve my understanding and skills in assembly, particularly regarding variable manipulation and control flow.
This is the code of my extern functions, that I did before:
section .text
global print
global print_num
global input
global int_to_string
global string_to_int
print:
call print_str
jmp exit_success
str_len:
push rbp
mov rbp, rsp
mov rax, 0
.str_len_loop:
cmp [rdi], byte 0
je .str_len_end
inc rdi
inc rax
jmp .str_len_loop
.str_len_end:
mov rsp, rbp
pop rbp
ret
print_str:
push rbp
mov rbp, rsp
push rdi
call str_len
pop rsi
mov rdx, rax
mov rax, 1
mov rdi, 1
syscall
mov rsp, rbp
pop rbp
ret
exit_success:
xor rdi, rdi
mov rax, 0
ret
print_num:
call print_str_num
jmp exit_success_num
str_len_num:
push rbp
mov rbp, rsp
mov rax, 0
.str_len_loop_num:
cmp [rdi], byte 0
je .str_len_end_num
cmp [rdi], byte 48
jl .str_len_end_num
cmp [rdi], byte 57
jg .str_len_end_num
inc rdi
inc rax
jmp .str_len_loop_num
.str_len_end_num:
mov rsp, rbp
pop rbp
ret
print_str_num:
push rbp
mov rbp, rsp
push rdi
call str_len_num
pop rsi
mov rdx, rax
mov rax, 1
mov rdi, 1
syscall
mov rsp, rbp
pop rbp
ret
exit_success_num:
xor rdi, rdi
mov rax, 0
ret
input:
push rbp
mov rbp, rsp
sub rsp, 8
mov rdi, 0
lea rsi, [rsp]
mov rdx, 8
mov rax, 0
syscall
mov r8, rax
mov rsp, rbp
pop rbp
ret
string_to_int:
mov rax, 0
.next_digit:
mov dl, byte [rsi]
inc rsi
cmp dl, 48
jl .fim
cmp dl, 57
jg .fim
sub dl, 48
imul rax, 10
add rax, rdx
jmp .next_digit
.fim:
mov rdx, 0
ret
int_to_string:
mov rbx, 10
.prox_digit:
mov rdx, 0
div rbx
add dl, '0'
dec rsi
mov byte [rsi], dl
cmp rax, 0
jnz .prox_digit
ret
I just tried to remove the variable, because I was using it in a wrong logic and was trying just to clean the code after I got the right output. Push/pop rdi
and rsi
doesn't fix the problem.
I'm a beginner in assembly and I'm encountering unexpected behavior in my code. The code works as expected, printing numbers from contador
variable to 1, but when I removed the unused variable loops
(which is not used anywhere in the code), it started printing random numbers infinitely. I don't understand why this happens.
Here’s the relevant part of the code:
extern print
extern input
extern string_to_int
extern int_to_string
extern print_num
section .data
contador dq 30
loops dq 10
v4 db " ", 10
section .bss
atual resb 1
section .text
global main
main:
push rbp
mov rbp, rsp
print_loop:
mov rax, [contador] ; pass the address
call int_to_string
push rsi
push rdi
mov rdx, [rsi]
mov [atual], rdx
mov rdi, atual
call print_num
mov rdi, v4
call print
dec qword [contador]
cmp qword [contador], 0
jne print_loop
pop rdi
pop rsi
mov rsp, rbp
pop rbp
mov rax, 60
mov rdi, 0
syscall
Why does the code start printing random numbers infinitely when I remove the loops
variable? Also, I would appreciate any tips or references to help improve my understanding and skills in assembly, particularly regarding variable manipulation and control flow.
This is the code of my extern functions, that I did before:
section .text
global print
global print_num
global input
global int_to_string
global string_to_int
print:
call print_str
jmp exit_success
str_len:
push rbp
mov rbp, rsp
mov rax, 0
.str_len_loop:
cmp [rdi], byte 0
je .str_len_end
inc rdi
inc rax
jmp .str_len_loop
.str_len_end:
mov rsp, rbp
pop rbp
ret
print_str:
push rbp
mov rbp, rsp
push rdi
call str_len
pop rsi
mov rdx, rax
mov rax, 1
mov rdi, 1
syscall
mov rsp, rbp
pop rbp
ret
exit_success:
xor rdi, rdi
mov rax, 0
ret
print_num:
call print_str_num
jmp exit_success_num
str_len_num:
push rbp
mov rbp, rsp
mov rax, 0
.str_len_loop_num:
cmp [rdi], byte 0
je .str_len_end_num
cmp [rdi], byte 48
jl .str_len_end_num
cmp [rdi], byte 57
jg .str_len_end_num
inc rdi
inc rax
jmp .str_len_loop_num
.str_len_end_num:
mov rsp, rbp
pop rbp
ret
print_str_num:
push rbp
mov rbp, rsp
push rdi
call str_len_num
pop rsi
mov rdx, rax
mov rax, 1
mov rdi, 1
syscall
mov rsp, rbp
pop rbp
ret
exit_success_num:
xor rdi, rdi
mov rax, 0
ret
input:
push rbp
mov rbp, rsp
sub rsp, 8
mov rdi, 0
lea rsi, [rsp]
mov rdx, 8
mov rax, 0
syscall
mov r8, rax
mov rsp, rbp
pop rbp
ret
string_to_int:
mov rax, 0
.next_digit:
mov dl, byte [rsi]
inc rsi
cmp dl, 48
jl .fim
cmp dl, 57
jg .fim
sub dl, 48
imul rax, 10
add rax, rdx
jmp .next_digit
.fim:
mov rdx, 0
ret
int_to_string:
mov rbx, 10
.prox_digit:
mov rdx, 0
div rbx
add dl, '0'
dec rsi
mov byte [rsi], dl
cmp rax, 0
jnz .prox_digit
ret
I just tried to remove the variable, because I was using it in a wrong logic and was trying just to clean the code after I got the right output. Push/pop rdi
and rsi
doesn't fix the problem.
1 Answer
Reset to default 4Why does the code start printing random numbers infinitely when I remove the loops variable?
Because your int_to_string was working from a non-initialized pointer RSI, the program was overwriting random memory, but not to a degree that it would crash the program. However, once the loops variable was removed, memory layout changed and this time the memory clobber was less forgiving.
Your number-printing solution is convoluted!
Once you have converted the number into a string, you should no longer be using those special case versions print_str_num and str_len_num. You already have text, so simply use the normal versions print_str and str_len.
First reserve some room for a small general-purpose buffer:
section .data
contador dq 30
section .bss
buffer resb 32
Modify the conversion routine so it takes in RDI the address beyond where the rightmost digit must go (and where you have prepared a space character, newline, and zero-terminator). Upon return RDI will conveniently point at the first leftmost digit in the string. Document any registers that get clobbered and/or preserve those that need preserving:
; IN (rax,rdi) OUT (rdi) MOD (rax,rbx,rdx)
int_to_string:
mov rbx, 10
.prox_digit:
xor edx, edx
div rbx
add dl, '0'
dec rdi
mov [rdi], dl
test rax, rax
jnz .prox_digit
ret
The main loop now becomes:
print_loop:
mov rdi, Buffer+28
mov dword [rdi], 00000A20h ; " ", 10, 0, 0
mov rax, [contador]
call int_to_string ; -> RDI (RAX RBX RDX)
call print
dec qword [contador]
jnz print_loop
Push/pop rdi and rsi doesn't fix the problem.
Indeed. Additionally you were pushing RSI/RDI multiple times inside the loop, and popping RDI/RSI just a single time outside the loop. That will have left a lot of RDIs and RSIs on the stack. You will always want to keep the stack balanced, what goes up must come down!
版权声明:本文标题:x86 64 - Why does the assembly code stop functioning right when I remove an unused variable? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736284908a1927348.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
int_to_string
does not haversi
set so it's overwriting random memory. You are lucky it even does something instead of crashing. Alsoatual resb 1
is just 1 byte but you use it as 8. – Jester Commented Jan 3 at 11:16mov [atual], rdx
is using 8 bytes. Yes, you should allocate a buffer but since you already haveatual
which is where I guess you want the result anyway you could use that after making it large enough. Also note thatint_to_string
writes backwards so you should pass the pointer to the end of the buffer. Furthermore, thepush rsi; push rdi
are useless and the matchingpop
s are outside the loop so you unbalance the stack (you are again lucky, because you terminate the program before that causes any problems). – Jester Commented Jan 3 at 17:45