x86-64 分段错误保存堆栈指针

2023-12-08

我目前正在关注本教程, 但我不是那所学校的学生。

GDB 给我一个分段错误thread_start在线上:

movq  %rsp, (%rdi)   # save sp in old thread's tcb

当我回溯时,这是附加信息:

#0  thread_start () at thread_start.s:16
#1  0x0000000180219e83 in _cygtls::remove(unsigned int)::__PRETTY_FUNCTION__
    () from /usr/bin/cygwin1.dll
#2  0x00000000ffffcc6b in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

作为一个新手,我一生都无法弄清楚为什么。这是我的主文件:

#define STACK_SIZE 1024*1024

//Thread TCB
struct thread {
    unsigned char * stack_pointer;
    void(*initial_function)(void *);
    void * initial_argument;
};

struct thread * current_thread;
struct thread * inactive_thread;

void thread_switch(struct thread * old_t, struct thread * new_t);
void thread_start(struct thread * old_t, struct thread * new_t);

void yield() {
    //swap threads
    struct thread * temp = current_thread;
    current_thread = inactive_thread;
    inactive_thread = temp;

    thread_switch(inactive_thread, current_thread);
}

void thread_wrap() {
   // call the thread's function
    current_thread->initial_function(current_thread->initial_argument);
    yield();
}

int factorial(int n) {
    return n == 0 ? 1 : n * factorial(n - 1);
}

// calls and print the factorial
void fun_with_threads(void * arg) {
    int n = *(int*)arg;
    printf("%d! = %d\n", n, factorial(n));
}
int main() {
    //allocate memory for threads
    inactive_thread = (struct thread*) malloc(sizeof(struct thread));
    current_thread = (struct thread*) malloc(sizeof(struct thread));

    // argument for factorial
    int *p= (int *) malloc(sizeof(int));
    *p = 5;

    // intialise thread
    current_thread->initial_argument =  p; 
    current_thread->initial_function = fun_with_threads;
    current_thread->stack_pointer = ((unsigned char*) malloc(STACK_SIZE)) + STACK_SIZE; 
    thread_start(inactive_thread, current_thread);
    return 0;
}

这是我的 thread_start 的 asm 代码

# Inline comment
/* Block comment */

# void thread_switch(struct thread * old_t, struct thread * new_t);

.globl thread_start

thread_start:
  pushq %rbx           # callee-save
  pushq %rbp           # callee-save
  pushq %r12           # callee-save
  pushq %r13           # callee-save
  pushq %r14           # callee-save
  pushq %r15           # callee-save

  movq  %rsp, (%rdi)   # save sp in old thread's tcb
  movq (%rsi), %rsp    # load sp from  new thread

  jmp thread_wrap

和线程开关:

# Inline comment
/* Block comment */

# void thread_switch(struct thread * old_t, struct thread * new_t);

.globl thread_switch

thread_switch:
  pushq %rbx           # callee-save
  pushq %rbp           # callee-save
  pushq %r12           # callee-save
  pushq %r13           # callee-save
  pushq %r14           # callee-save
  pushq %r15           # callee-save
  movq  %rsp, (%rdi)   # save sp in old thread's tcb
  movq (%rsi), %rsp    # load sp from  new thread
  popq  %r15           # callee-restore
  popq  %r14           # callee-restore
  popq  %r13           # callee-restore
  popq  %r12           # callee-restore
  popq  %rbp           # callee-restore
  popq  %rbx           # callee-restore
  ret                  # return

你在使用 cygwin,对吗?它默认使用 Windows x64 调用约定,而不是 System V x86-64 psABI。所以你的参数不在%rdi and %rsi.

调用约定是 Windows x64,但 ABI 略有不同:long是 64 位,所以它是 LP64 而不是 LLP64。看cygwin 文档.

您可以使用以下命令覆盖默认值__attribute__((sysv_abi))在原型上,但这仅适用于理解 GNU C 的编译器。


Agner Fog 的通话约定指南对于如何编写在 Windows 和非 Windows 上组装成工作函数的源代码有一些建议。最直接的事情是使用#ifdef选择不同的功能序言。


This Intel x64 汇编简介有点以 Windows 为中心,详细介绍了 Windows x64__fastcall调用约定。

(后面是示例和其他内容。这是一个相当大且很好的教程,从非常基本的内容开始,包括如何使用汇编器等工具。我推荐它用于在 Windows 开发环境中学习 x86-64 asm,也许一般来说。)

Windows x64__fastcall(如 x64__vectorcall但不传递向量regs中的向量)

  • RCX、RDX、R8、R9 用于整数和指针参数按从左到右的顺序
  • XMM0、1、2 和 3 用于浮点参数。
  • 其他参数从左到右压入堆栈。
  • 长度小于 64 位的参数不进行零扩展;高位包含垃圾。
  • 调用者有责任在调用之前分配 32 字节的“影子空间”(如果需要,用于存储 RCX、RDX、R8 和 R9) 功能。
  • 调用者有责任在调用后清理堆栈。
  • 如果 64 位或更少,则在 RAX 中返回整数返回值(类似于 x86)。
  • 浮点返回值在 XMM0 中返回。
  • 较大的返回值(结构)由调用者在堆栈上分配空间,并且 RCX 在以下情况下包含指向返回空间的指针: 被调用者被调用。整数参数的寄存器用法是 将其中一个推到右边。 RAX 将此地址返回给调用者。
  • 堆栈是 16 字节对齐的。 “call”指令推送一个 8 字节的返回值,因此所有非叶函数必须调整 分配堆栈空间时,按 16n+8 形式的值堆栈。
  • 寄存器 RAX、RCX、RDX、R8、R9、R10 和 R11 被视为易失性寄存器,必须在函数调用时被视为已销毁。 RBX、RBP、 RDI、RSI、R12、R14、R14 和 R15 必须保存在使用的任何函数中 他们。
  • 请注意,浮点(以及 MMX)寄存器没有调用约定。
  • 更多详细信息(可变参数、异常处理、堆栈展开)请访问 Microsoft 的站点。

链接到 MS 的调用约定文档x86tag wiki(以及 System V ABI 文档,以及大量其他好东西)。

也可以看看为什么 Windows64 使用与 x86-64 上所有其他操作系统不同的调用约定?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

x86-64 分段错误保存堆栈指针 的相关文章

  • 编译时运算符

    有人可以列出 C 中可用的所有编译时运算符吗 C 中有两个运算符 无论操作数如何 它们的结果始终可以在编译时确定 它们是sizeof 1 and 2 当然 其他运算符的许多特殊用途可以在编译时解决 例如标准中列出的那些整数常量表达式 1 与
  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • 通过 CMIS (dotCMIS) 连接到 SP2010:异常未经授权

    我正在使用 dotCMIS 并且想要简单连接到我的 SP2010 服务器 我尝试用 C 来做到这一点 如下所示http chemistry apache org dotnet getting started with dotcmis htm
  • 为什么 C# Array.BinarySearch 这么快?

    我已经实施了一个很简单用于在整数数组中查找整数的 C 中的 binarySearch 实现 二分查找 static int binarySearch int arr int i int low 0 high arr Length 1 mid
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 为什么编译时浮点计算可能不会得到与运行时计算相同的结果?

    In the speaker mentioned Compile time floating point calculations might not have the same results as runtime calculation
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • 如何使用 jQuery 查找文本并替换

    我试图找到一个解决方案来搜索 DOM 中包含的文本字符串 Tony 并将其替换为文本字符串 Tiger 有人对如何做到这一点有任何见解或想法吗 我猜它需要每个语句加上替换函数并且可能包含 谢谢 杰克 您可以使用它来搜索 body 元素的所有
  • Symfony2:AJAX请求:如何在需要时处理身份验证?

    使用 Symfony2 我实现了 AJAX 操作来管理应用程序中的一些书签 添加 删除 因此 用户需要经过身份验证才能继续 我有一个将用户重定向到登录页面的解决方案 但我认为最好使用事件来处理此重定向 实际解决方案 检查用户身份验证的方式与
  • 将条件应用于 MongoDB 中同一字段的多个文档

    我有一个具有以下结构的文档 user id 123 tag tag1 user id 123 tag tag2 user id 123 tag tag3 user id 456 tag tag1 给定用户 ID 我想查找该用户是否拥有包含所
  • 如何在 phing 中迭代(循环)目录?

    我想为一些插件创建 phing 任务 所以目录结构类似于 root plugin1 index php plugin2 index php etc 我想在每个子目录上运行相同的任务 例如 为plugin1生成文档 为plugin1运行单元测
  • Python MySQLdb 字符串替换不添加引号

    我想对逗号分隔的列表使用字符串替换 例如 query SELECT id name image id FROM users WHERE id IN s values join uids results dbc getAll query va
  • Java中的邻接矩阵

    我对图表和邻接矩阵感到非常困惑 我正在为一个类做作业 其中我有一个节点的文本文件和一个边的文本文件 我必须读取它们中的每一个并将它们制作为一个图表 然后我可以在其中执行操作 例如确定图表是否是连接 寻找最小生成树 遍历并寻找路径 不过 我以
  • 带有嵌入字体的 @font-face 不起作用

    我有网站 http kuvaklubi fi我尝试使用字体的地方 Century Gothic 我的电脑上不存在此字体 Installed fonts 我想通过以下方式将此字体嵌入到 css 中 font face 我已经生成了一些字体文件
  • django.db.backends.dummy 和 django.db.backends.mysql 有什么区别?

    django db backends dummy 和 django db backends mysql 有什么区别 我发现有人使用dummy和mysql 但我搜索后不知道他们的区别 django db backends mysql后台数据库
  • 获取类层次结构的所有字段[重复]

    这个问题在这里已经有答案了 我有课 ClassA public String filedA ClassB extends ClassA public String filedB ClassC extends ClassB public St
  • 使用spatiallite 将 GIS 缓冲值度以米为单位

    我是 Spatialite 的新手 我有以下查询 select A from linka as A pointa as B where Contains Buffer B Geometry 100 A Geometry 我实际上想创建 10
  • 强制一种方法等待另一种方法完成

    在我的原始视图控制器中 在转到目标视图控制器之前 我调用一个获取关键参数的方法 然后在以下方法中在目标视图控制器中设置关键参数 然而 关键参数是在之前设置的doSomethingToGetKey方法已完成 因此传递了一个空值 我想知道是否有
  • 如何创建自己的资源名称?

    我可以在中使用我自己的资源名称吗themes xml 例如
  • 由于未注册 Windows.Launch 合同,Windows 10 分配的访问应用程序无法启动

    我有一个 WPF 应用程序 我已使用以下命令将其转换为 UWP 应用程序DesktopAppConverter为了运行它分配的访问权限模式 转换后的应用程序在非分配访问模式下运行时可以工作 可以安装并正常运行 但是 当我将其设置为分配的访问
  • 无法使用 cURL 将 SSH 密钥发送到 Github

    我正在尝试将我的公共 ssh 密钥发送到 Github 我将密钥设置为 shell 中的变量 但它给出了key is invalid You must supply a key in OpenSSH public key format错误
  • 在堆栈弹出中反应本机路由通量重新渲染组件

    如何重新运行 React 组件生命周期方法来确定在从堆栈转换回以前的屏幕时是否需要重新渲染React Native 路由器 Flux 设想 场景 A gt B gt A 假设 A 是初始场景 我们使用 a 从 A 导航到 B推即 Actio
  • 为什么我们先复制然后移动?

    我在某处看到代码 其中有人决定复制一个对象 然后将其移动到类的数据成员 这让我感到困惑 因为我认为移动的全部目的是为了避免复制 这是示例 struct S S std string str data std move str 这是我的问题
  • 带有列表和字典的嵌套循环

    所以我有点陷入了一个问题 本质上 我想使用列表和字典运行一个嵌套循环 但我似乎不知道如何操作 我的用例是运行一个 playbook 它将通过使用主体列表签署公钥来生成 SSH 证书 我有一个充当跳转主机的主机列表 称为 bastionHos
  • 如何获取java日历中每月第一个星期三的日期

    我如何使用java日历类获取该月下一个第一个星期三的日期 例如 Today 24 03 2012 the next first Wednesday will be 04 04 2012 On 05 04 2012 the next firs
  • 这个预提交钩子如何修复尾随空格?

    发生了什么事这个预提交钩子 我认为更改文件会导致它们被重新暂存 bin sh A git hook script to find and fix trailing whitespace in your commits Bypass it w
  • x86-64 分段错误保存堆栈指针

    我目前正在关注本教程 但我不是那所学校的学生 GDB 给我一个分段错误thread start在线上 movq rsp rdi save sp in old thread s tcb 当我回溯时 这是附加信息 0 thread start