所以我正在尝试学习一点装配,因为我需要它用于计算机体系结构类.我写了一些程序,比如打印Fibonacci序列.
我认识到每当我编写程序时,我都会使用这3行(正如我从比较生成的汇编代码中学gcc到的那样C):
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
Run Code Online (Sandbox Code Playgroud)
我有2个问题:
%rbp?使用起来不是很简单%rsp,因为它的内容被移到%rbp了第二行吗?%rsp?我的意思是并非总是16(当我在printf第7行或第8行变量时,我会减去24或减去28我在虚拟机(4 GB RAM),Intel 64位处理器上使用Manjaro 64位
鉴于这段代码:
swap:
push ebp ; back up the base pointer,
mov ebp, esp
; push the context of the registers on the stack
push eax
push ebx
push ecx
push edx
mov eax, [ebp+8] ; address of the first parameter
mov ebx, [ebp+12] ; address of the second parameter
mov dl, [eax]
mov cl, [ebx]
mov [eax], cl
mov [ebx], dl
; restore the context of the registers from the stack
pop edx
pop ecx
pop ebx
pop eax
; …Run Code Online (Sandbox Code Playgroud) 我在vs2008中编译一个c ++静态库,在解决方案中我也有一个使用lib的启动项目,并且工作正常.
但是当在另一个解决方案中使用lib时,我得到运行时检查失败."ESP的值没有在功能调用中正确保存"通过代码我注意到函数foo()在崩溃之前跳转到bar().有问题的函数只是常规函数而没有函数指针.
任何人都知道可能会发生什么,以及为什么它在使用同一解决方案中的lib时有效?
编辑:函数(方法)是类的一部分,如果有帮助的话.
例如,如果我按下ax,[SP]指向我的ax值或ax之后的单词?它是否与实模式保护模式不同?我问这个是因为汇编书的艺术说明和解释为最后推送数据的sp点,并且在这个页面上OSDev Wiki -在最后推送数据之后它指向空白字的堆栈.
对于 RISC-V,堆栈指针是否指向压入堆栈的最后一个数据,或者堆栈的下一个空闲地址位置?
当堆栈指针在程序的最开始处初始化时(例如crt.S)(即堆栈为空),堆栈指针是否应该初始化为指向第一个字将被压入的内存位置或之前的地址?(例如,假设堆栈的第一个元素将在 4092 处压入。那么,堆栈指针是从 4096 还是 4092 开始?)
指向其定义位置的指针将不胜感激。
我观察到 GCC 的 C++ 编译器生成以下汇编代码:
sub $0xffffffffffffff80,%rsp
Run Code Online (Sandbox Code Playgroud)
这相当于
add $0x80,%rsp
Run Code Online (Sandbox Code Playgroud)
即从堆栈中删除 128 个字节。
为什么 GCC 生成第一个子变体而不是添加变体?对我来说,添加变体似乎比利用下溢更自然。
在相当大的代码库中,这只发生一次。我没有最小的 C++ 代码示例来触发此操作。我正在使用海湾合作委员会7.5.0
NASM 程序集,Ubuntu,32 位程序。
通常,当从堆栈中弹出一个值时,我会做
POP somewhere
Run Code Online (Sandbox Code Playgroud)
放入寄存器或变量。但有时,我只是不想把它放在任何地方——我只想摆脱堆栈中的下一个元素。正在做
POP
Run Code Online (Sandbox Code Playgroud)
就像那样是行不通的。
我的解决方法是制作一个我根本不使用的 4 字节变量并将其转储POP到其中。有没有更好的方法来实现这一目标?
在x86程序集中,是否可以从堆栈中删除值而不存储它?有什么东西沿着pop word null?我显然可以使用add esp,4,但也许有一个很好的和干净的cisc助记符我不见了?
我的代码中有这个代码段
void jmp_esp()
{
__asm__("jmp *%esp");
}
Run Code Online (Sandbox Code Playgroud)
用gcc编译时
gcc aslr.c -o aslr -ggdb -fno-stack-protector -z execstack
Run Code Online (Sandbox Code Playgroud)
我收到这个错误.
aslr.c: Assembler messages:
aslr.c:6: Error: operand type mismatch for `jmp'
Run Code Online (Sandbox Code Playgroud)
尽管汇编指令有效,为什么这行无法编译?
我读过有关DEP(数据执行预防)的文章.可能是这个功能正在创建这个编译错误?如果是的话,如何禁用它?
我正在尝试制作一个适用于两种架构的引导加载程序:x86 和 PDP-11。主操作系统是为 PDP-11 兼容机器编写的,但从 x86 启动也应该可以工作,启动模拟器。
AFAIK,如果最后两个字节是, x86 加载第一个磁盘扇区0x7c00并跳转到那里。相反,如果第一个命令是且最后两个字节是 ,则 PDP-11 兼容机将第一个扇区加载到(八进制)并执行它。然而,由于一些硬件细节的原因,加载的数据实际上是颠倒的——例如,x86 读取的数据,另一台机器读取的数据。在这种情况下,这在某种程度上是一个功能,因为如果我制作最后两个字节,它们将适用于两台机器。0x55 0xaa0o20000NOP0xaa 0x550x120xed0x55 0xaa
总之,PDP-11兼容机需要前两个字节包含NOP命令,即0o000240,或0x00a0。数据被反转,因此 x86 实际上会读取0xff5f。
0x5f是 x86 中的真实命令。不幸的是,它是pop di. AFAIK,sp和ss值都没有指定,所以这个命令读取谁知道什么。
我的问题是:
0x0000:0x0000or 0xffff:0xffff?ss:sp指向读取不安全的内存映射硬件寄存器?如果是的话,如果我读了它们,会发生什么更糟糕的事情?我不想意外损坏笔记本电脑。ss:sp指向不可用的内存,即可能pop di触发总线错误?如果是,BIOS 将如何从中恢复,即它将重新启动、显示消息或执行其他操作?stack-pointer ×10
assembly ×8
x86 ×6
stack ×3
c ×2
c++ ×2
nasm ×2
bootloader ×1
callstack ×1
gcc ×1
riscv ×1
stack-memory ×1
static ×1
x86-16 ×1
x86-64 ×1