增加 rsp 是否等于 pop?
Does incrementing rsp is equal to pop?
我是汇编新手,我想编写一个函数来在汇编中打印数字并从 C++ 中调用它,请参阅下面的代码
cpp:
#include <iostream>
#include <stdint.h>
extern "C" void printunum(uint64_t);
int main()
{
printunum(12345);
std::cout<<std::endl;
return 0;
}
程序集:
global printunum
section .text
printunum:
mov rax,rdi
mov rdi,10
mov rsi,0
while1:
cmp rax,0
je endwhile1
mov rdx,0
div rdi
inc rsi
add rdx,48
push rdx
jmp while1
endwhile1:
mov r10,rsi
while2:
cmp r10,0
je endwhile2
mov rax,1
mov rdi,1
mov rsi,rsp ;to pass memory address
add rsp,8 ;it is equal to pop or it is wrong and it will add 8 bytes here?
mov rdx,1
syscall
dec r10
jmp while2
endwhile2:
ret
已编辑程序集:
global print_uint64
section .text
print_uint64:
;init
mov rax,rdi
mov rdi,10
mov rsi,rsp
;endinit
while:
xor rdx ,rdx
div rdi
add rdx ,48
dec rsi
mov [rsi],dl
cmp rax ,0
je else
if:
jmp while
else:
endwhile:
;print
mov rax,1
mov rdi,1
mov rdx,rsp
sub rdx,rsi
syscall
;endprint
;return
mov rax,rsp
sub rax,rsi
ret
我编译:
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$ nasm -f elf64 asm.asm
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$ g++ main.cpp asm.o -o main
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$ ./main
12345
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$
我的处理器 amd64(x86-x64),我正在使用 kali linux
1)上面的代码没有错(pop在x64位机器上等于rsp+8)
2)mul运算将结果放入rdx:rax我如何将它放入单个内存
3)div 操作从 rdx:rax 获取 dividend 我怎样才能将单个值放入 rdx:rax。
感谢您的答复。
POP
所做的是:
- 将数据从
[RSP]
移动到目标寄存器
- 将寄存器的大小添加到
RSP
所以如果你不需要实际使用堆栈中的数据,你可以直接将数据的大小添加到RSP
,它具有相同的效果
此示例包含对先前评论中的一些建议的修复,并且比您的版本短 24 个字节。此外,一些数学运算已经完成,因为 RBX 和 RDI 之间的差异与在 R10[ 中使用计数器相同=18=].
尽管使用 push 构建字符串是一个新颖的想法,但正如指出的那样,在某些系统上,每个字符的 7 个 NULL 可能会导致问题,而且不仅会造成不必要的大缓冲区。
global printnum
section .text
printnum:
; The maximum signed 64 bit value ( 9223372036854775807 ) needs a maximum of 19 digits or
; 20 for unsigned values. Create a buffer on the stack suitably large enough for that.
push rbp
mov rbp, rsp
sub rsp, 32 ; Reserve 32 bytes so stack stays QWORD aligned.
mov rax, rdi ; Move value passed by caller to be converted.
mov rdi, rbp ; Establish pointer to next byte past EOS (End of String).
mov ecx, 10 ; Divisor
LtoA:
xor edx, edx
div rcx
or dl, '0'
dec rdi ; This way RDI always points to most recent character written.
mov [rdi], dl ; Essentially DL = RAX % 10.
test rax, rax
jnz LtoA
showString:
mov al, 1 ; Equivalent to SYS_WRITE.
mov rsi, rdi ; RSI points to beginning of string.
mov edi, eax ; Equivalent to STDOUT.
mov rdx, rbp
sub rdx, rsi ; Number of byte to be displayed.
syscall
leave
ret
我是汇编新手,我想编写一个函数来在汇编中打印数字并从 C++ 中调用它,请参阅下面的代码
cpp:
#include <iostream>
#include <stdint.h>
extern "C" void printunum(uint64_t);
int main()
{
printunum(12345);
std::cout<<std::endl;
return 0;
}
程序集:
global printunum
section .text
printunum:
mov rax,rdi
mov rdi,10
mov rsi,0
while1:
cmp rax,0
je endwhile1
mov rdx,0
div rdi
inc rsi
add rdx,48
push rdx
jmp while1
endwhile1:
mov r10,rsi
while2:
cmp r10,0
je endwhile2
mov rax,1
mov rdi,1
mov rsi,rsp ;to pass memory address
add rsp,8 ;it is equal to pop or it is wrong and it will add 8 bytes here?
mov rdx,1
syscall
dec r10
jmp while2
endwhile2:
ret
已编辑程序集:
global print_uint64
section .text
print_uint64:
;init
mov rax,rdi
mov rdi,10
mov rsi,rsp
;endinit
while:
xor rdx ,rdx
div rdi
add rdx ,48
dec rsi
mov [rsi],dl
cmp rax ,0
je else
if:
jmp while
else:
endwhile:
;print
mov rax,1
mov rdi,1
mov rdx,rsp
sub rdx,rsi
syscall
;endprint
;return
mov rax,rsp
sub rax,rsi
ret
我编译:
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$ nasm -f elf64 asm.asm
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$ g++ main.cpp asm.o -o main
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$ ./main
12345
srilakshmikanthanp@HP-245-G5-NOTEBOOK-PC:~/Documents/Learn$
我的处理器 amd64(x86-x64),我正在使用 kali linux
1)上面的代码没有错(pop在x64位机器上等于rsp+8)
2)mul运算将结果放入rdx:rax我如何将它放入单个内存
3)div 操作从 rdx:rax 获取 dividend 我怎样才能将单个值放入 rdx:rax。 感谢您的答复。
POP
所做的是:
- 将数据从
[RSP]
移动到目标寄存器 - 将寄存器的大小添加到
RSP
所以如果你不需要实际使用堆栈中的数据,你可以直接将数据的大小添加到RSP
,它具有相同的效果
此示例包含对先前评论中的一些建议的修复,并且比您的版本短 24 个字节。此外,一些数学运算已经完成,因为 RBX 和 RDI 之间的差异与在 R10[ 中使用计数器相同=18=].
尽管使用 push 构建字符串是一个新颖的想法,但正如指出的那样,在某些系统上,每个字符的 7 个 NULL 可能会导致问题,而且不仅会造成不必要的大缓冲区。
global printnum
section .text
printnum:
; The maximum signed 64 bit value ( 9223372036854775807 ) needs a maximum of 19 digits or
; 20 for unsigned values. Create a buffer on the stack suitably large enough for that.
push rbp
mov rbp, rsp
sub rsp, 32 ; Reserve 32 bytes so stack stays QWORD aligned.
mov rax, rdi ; Move value passed by caller to be converted.
mov rdi, rbp ; Establish pointer to next byte past EOS (End of String).
mov ecx, 10 ; Divisor
LtoA:
xor edx, edx
div rcx
or dl, '0'
dec rdi ; This way RDI always points to most recent character written.
mov [rdi], dl ; Essentially DL = RAX % 10.
test rax, rax
jnz LtoA
showString:
mov al, 1 ; Equivalent to SYS_WRITE.
mov rsi, rdi ; RSI points to beginning of string.
mov edi, eax ; Equivalent to STDOUT.
mov rdx, rbp
sub rdx, rsi ; Number of byte to be displayed.
syscall
leave
ret