标签: stack-pointer

使用"jmp*%esp"时操作数类型不匹配

我的代码中有这个代码段

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(数据执行预防)的文章.可能是这个功能正在创建这个编译错误?如果是的话,如何禁用它?

c assembly stack-pointer

5
推荐指数
1
解决办法
264
查看次数

谁定义了栈指针地址

对于有C启动代码的微控制器和嵌入式系统来说,C启动代码的功能之一就是初始化堆栈指针。

这个初始栈指针地址和C启动代码一般是芯片厂商定义和提供的吗?

还是由我们作为固件/软件开发人员手动修改或创建 C 启动代码并指定堆栈指针?这部分让我感到困惑。

c embedded microcontroller startup stack-pointer

5
推荐指数
1
解决办法
579
查看次数

如果变量离开作用域,为什么C不会递减堆栈指针?

#include <stdio.h>
void main() {
    {
        int x;
        printf("%p\n", &x);
    }
    {
        int x;
        printf("%p\n", &x);
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为运行此命令将输出相同的内容两次。当它声明第一个变量时,它会递增堆栈指针,但会离开作用域,因此会递减它,然后第二次重复该过程,因此int x两次都将占用堆栈上的相同内存位置。

但是事实并非如此。堆栈指针不会递减,int x在两种情况下都将占用堆栈中的不同位置。实际上,int x即使范围已消失,第一个仍然可以访问。

#include <stdio.h>
void main() {
    {
        int x = 10;
        printf("%p\n", &x);
    }
    {
        int x = 25;
        printf("%p\n", &x);
    }
    {
        int x = 71;
        printf("%p\n", &x);

        int *p = &x;
        printf("%i %i %i\n", *(p + 2), *(p + 1), *p);
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么是这样?我有什么误会?

c stack-pointer

5
推荐指数
2
解决办法
129
查看次数

在引导加载程序启动时读取堆栈安全吗?

背景

我正在尝试制作一个适用于两种架构的引导加载程序: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,spss值都没有指定,所以这个命令读取谁知道什么。

我的问题是:

  • 在实践中,我可以假设它们要么指向有效的堆栈,要么都设置为某个占位符,例如0x0000:0x0000or 0xffff:0xffff
  • 可能ss:sp指向读取不安全的内存映射硬件寄存器?如果是的话,如果我读了它们,会发生什么更糟糕的事情?我不想意外损坏笔记本电脑。
  • 可能ss:sp指向不可用的内存,即可能pop di触发总线错误?如果是,BIOS 将如何从中恢复,即它将重新启动、显示消息或执行其他操作?

x86 assembly bootloader x86-16 stack-pointer

5
推荐指数
0
解决办法
130
查看次数

我可以使用 rsp 作为通用寄存器吗?

有人告诉我,如果我用作rsp通用寄存器,操作系统可能会将寄存器转储到它在中断时指向的位置,从而导致出现问题的行为。

这是真的吗?如果不是,那么如果我不需要堆栈,我可以将其rsp用作通用寄存器吗?

编辑:在用户空间中运行。

assembly x86-64 cpu-registers stack-pointer

4
推荐指数
1
解决办法
606
查看次数

作为副作用影响 ESP 的 x86 指令是什么?

我知道call并且ret会修改espand that的值push并且pop有许多变体,但是还有其他指令会影响堆栈指针吗?

x86 assembly callstack stack-pointer

4
推荐指数
1
解决办法
967
查看次数

x86-CPU 上堆栈指针到底指向哪里?到顶部元素还是在它后面?

在一些教程中,据说堆栈指针指向堆栈的顶部元素:

+-------------+
|    stack    |
+-------------+
| top element |  <-- esp
+-------------+
Run Code Online (Sandbox Code Playgroud)

在其他情况下,据说它指向它的后面,因此指向堆栈增长时可以写入的第一个内存地址。

+-------------+
|    stack    |
+-------------+
| top element | 
+-------------+  <-- esp
Run Code Online (Sandbox Code Playgroud)

在这个德国维基百科网站 https://de.wikipedia.org/wiki/Register_(Computer)#Stapelregister上 ,据说两个版本都存在,并且取决于 CPU 架构。

我的问题是,它在 x86-CPU 上表现如何?它也取决于操作系统吗?

assembly stack cpu-architecture cpu-registers stack-pointer

4
推荐指数
1
解决办法
1922
查看次数

这种用于堆栈切换的内联asm方法可以吗?

对于某些功能,我需要切换堆栈以使原始堆栈保持不变。为此,我编写了两个宏,如下所示。

#define SAVE_STACK()    __asm__ __volatile__ ( "mov %%rsp, %0; mov %1, %%rsp" : \
"=m" (saved_sp) : "m" (temp_sp) );
#define RESTORE_STACK() __asm__ __volatile__ ( "mov %0, %%rsp" : \
"=m" (saved_sp) );
Run Code Online (Sandbox Code Playgroud)

这里temp_spsaved_sp是线程局部变量。temp_sp指向我们使用的临时堆栈。对于一个我希望不修改其原始堆栈的函数,我将 SAVE_STACK 放在开头,将 RESTORE_STACK 放在底部。例如,像这样。

int some_func(int param1, int param2)
{
 int a, b, r;
 SAVE_STACK();
 // Function Body here
 .....................
 RESTORE_STACK();
 return r;
}
Run Code Online (Sandbox Code Playgroud)

现在我的问题是这种方法是否可行。在 x86(64 位)上,局部变量和参数是通过rbp寄存器访问的,并且rsp在函数序言中相应地被减去,直到在函数尾声中才被触及,在函数结尾中将其添加到原始值。因此,我认为这里没有问题。

我不确定在存在上下文切换和信号的情况下这是否正确。(在 Linux 上)。另外,我不确定如果函数是内联的,或者是否应用尾部调用优化(使用jmp而不是call ),这是否正确。您发现这种方法有任何问题或副作用吗?

c gcc x86-64 inline-assembly stack-pointer

3
推荐指数
1
解决办法
399
查看次数

在armv8架构中将半字值存储到堆栈内存中时出现总线错误?

我有两个寄存器 w1 和 w2,我想将它们存储在堆栈上。我想将完整的单词w1和w2的一半存储到堆栈中。这是我的实现:

STR w1, [sp, #-8]!
STRH w2, [sp, #-8]!
Run Code Online (Sandbox Code Playgroud)

编译时,第一条指令运行良好,但第二条指令引发总线错误。我知道这是一些对齐问题,但我无法正确理解为什么会发生这种情况?

我正在针对 ARMv8(64 位)架构进行编译。

assembly memory-alignment bus-error arm64 stack-pointer

3
推荐指数
1
解决办法
1091
查看次数

为什么rsp寄存器从0x7FFFFFFFDD0开始

我正在学习x86汇编,使用下面的代码进行测试,我在gdb控制台中看到指向堆栈顶部的rsp寄存器从0x7FFFFFFFDFD0开始,如果我理解正确的话,在代码中我没有使用push或pop修改 rsp,因此 0x7FFFFFFFDFD0 它是默认值,这意味着我们在堆栈中具有相同的字节数,但我使用堆栈大小为 8mb 的 Linux

section .text
global _start
_start:

mov rcx, 2
add rcx, 8

mov rax, 0x1
mov rbx, 0xff
int 0x80
Run Code Online (Sandbox Code Playgroud)

linux assembly x86-64 stack-memory stack-pointer

3
推荐指数
1
解决办法
186
查看次数