- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我最近才开始我的汇编之旅,所以显然我是一个新手,我一直在编写相当简单和基本的程序,我只是注意到一些奇怪的东西(对我来说)。
一个程序给出以二进制形式以 111 结尾的表中数字的计数
入口点:
#include <iostream>
#include <cstdlib>
extern "C" auto _start(void *, void *)->void;
auto print_msg(char *msg) {
std::cout << msg;
}
auto print_int(uint64_t val) {
std::cout << val;
}
auto main()->int {
_start(print_int, print_msg);
std::cout << std::endl;
system("pause");
}
程序集:
.const
_tab dw 65535, 61951, 61949, 61925, 61927, 61734, 61735, 61728
_LENGTH = ($ - _tab) / 2
_msg_1 db 'There are ', 0
_msg_2 db ' numbers ending with 111 in binary!', 0
.code
_start proc
push r15
push r14
sub rsp, 32 + 16
mov r14, rcx
mov r15, rdx
xor rcx, rcx
xor r9, r9
lea r8, _tab
_LOOP: movzx rax, word ptr [r8]
and rax, 111b
cmp rax, 111b
jz _INC
jmp _END_IF
_INC: inc rcx
_END_IF: inc r9
add r8, 2
cmp r9, _LENGTH
jne _LOOP
mov [rsp + 32], rcx
lea rcx, _msg_1
call r15
mov rcx, [rsp + 32]
sub rsp, 8
call r14
add rsp, 8
lea rcx, _msg_2
call r15
add rsp, 32 + 16
pop r14
pop r15
ret
_start endp
end
如果我在“call r14”周围注释“sub rsp, 8”和“add rsp, 8”,程序会立即崩溃,这对我来说没有意义,我想知道为什么会这样,并且另外,如果我用“push rcx”和“pop rcx”替换“mov [rsp + 32],rcx”和“mov rcx,[rsp + 32]”,输出将是垃圾,我也很好奇
最佳答案
Windows x64 calling convention在 CALL 指令之前需要 RSP 的 16B 对齐(但因此 保证 rsp%16 == 8
在函数入口,在 call
推送返回地址之后).这解释了围绕函数调用的 sub rsp,8
。
它还需要 32B 的影子空间(又名 home space )为被调用函数的使用保留,这就是 sub rsp, 32 + 16
正在做的事情。
将它们组合在一起会很聪明,sub rsp, 32 + 16 + 8
在函数入口处,然后在尾声之前不要弄乱 RSP。 (在执行奇数次 push
es 的函数中,负责 +8
以重新对齐堆栈。)
[rsp+32]
和高位字节不会被 call
踩踏,低位字节则不然。
被调用函数可以自由使用其返回地址上方的 32 个字节。这解释了为什么如果你只是在 CALL 周围压入/弹出,你会得到乱码输出,因为那样你的数据将在阴影空间中。
参见 x86为 ABI/调用约定链接标记 wiki。
关于windows - 为什么我必须使用 "rsp"来调用 C++ 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40344385/
考虑以下几点: ammarfaizi2@integral:/tmp$ vi test.c ammarfaizi2@integral:/tmp$ cat test.c extern void use_b
您可以阅读有关 64 位调用约定的信息 here . x64 函数应该自行清理,但是,当我从 .asm 调用 malloc 时,它会覆盖 RSP 和 RSP+8 处的值。这似乎是非常错误的。有什么建议
使用ptrace获取另一个进程的寄存器时,有没有可能是停止点在内核空间(做系统调用之类的在sleep()),RIP在内核代码段,RSP是内核堆栈指针? 最佳答案 is it possible ...
有问题Compilers: Understanding assembly code generated from small programs编译器使用两个局部变量而不调整堆栈指针。 不调整 RSP
有问题Compilers: Understanding assembly code generated from small programs编译器使用两个局部变量而不调整堆栈指针。 不调整 RSP
我无法理解堆栈的工作原理。首先是我的小代码: void func1 ( int z ) { int i = 1; } int main ( ) { func1 ( 89 ); return
我第一次学习汇编语言。这是(gdb)反汇编的一部分: mov $0x131,%eax cmp 0x8(%rsp),%eax //Question here, what is the va
有人告诉我,如果我使用 rsp 作为通用寄存器,操作系统可能会将寄存器转储到它在中断时指向的位置,从而导致出现问题的行为。 这是真的吗?如果不是,如果我不需要堆栈,我可以使用 rsp 作为通用寄存器吗
对于我们的一个应用程序,我们在/var/log/messages 中看到了以下提到的几条消息: Sep 18 03:24:23 kernel: application_name[14682] tra
我在 CSharpInteractive.rsp 中看到您可以使用/r 在 GAC 中添加对 DLL 的引用: 如何添加对自己的 DLL 的引用? 我试过 System.Reflection.Asse
让我们采用以下基本 C 函数及其生成的有意未优化的程序集: int main() { int i = 4; return 3; } 它生成以下(未优化的)程序集,这对我来说都很有意义:
我研究了 32 位机器,我知道 sub $12, %esp 与 pop %eax 和 mov $0, %eax 上的三次相同。 但我不知道为什么我们在 x86-64 机器上使用 add $18, %r
下面是我的代码: C代码 // this function might look weird, just for demo purpose void func4(int x, int y, int z
下面是我的代码: C代码 // this function might look weird, just for demo purpose void func4(int x, int y, int z
在汇编中,许多函数以下面的序言开始: 00000001004010e0: main(int, char**)+0 push %rbp 00000001004010e1: main(int,
考虑以下x64 NASM语法程序集: inc qword [rax] inc qword [rcx] inc qword [rdx] inc qword [rbx] inc qword [rsp] i
这个问题是关于 x86 汇编的,但我用 C 提供了一个例子,因为我试图检查 GCC 在做什么。 当我遵循各种汇编指南时,我注意到人们,至少是我阅读过的 Material 中的少数人,似乎习惯于将堆栈变
我是内联汇编的新手。我有以下带有内联汇编的 C 函数。我只是想看看 push %%rbp 和 mov %%rsp, %%rbp 是否实际运行正确。我的功能如下, test_inlineAssembly
我目前正在使用 gcc、gdb 和汇编并试图理解它们。我已经复习了一些教程并掌握了一些关键点。 所以我决定使用一个小的 .c 文件,看了一下结果,有些事情不是很清楚。 这是文件: #include
根据 Intel 在 x64 中的说法,以下寄存器称为通用寄存器(RAX、RBX、RCX、RDX、RBP、RSI、RDI、RSP 和 R8-R15)https://software.intel.com
我是一名优秀的程序员,十分优秀!