如何在 MASM 中为近直接相对调用/jmp 编写绝对目标

2024-02-02

成为正常(近直系亲属)call到您编写的 NASM 或 AT&T 语法中的绝对地址call 0x1234567,汇编器+链接器负责计算arel32从链接器放置的任何地方到达该目标call操作说明。

例如在 Linux 上将其组装成静态 64 位 ELF 可执行文件yasm -felf64 foo.asm && ld foo.o -o foo,然后用objdump -drwC -Mintel foo给你:

foo:     file format elf64-x86-64
Disassembly of section .text:
0000000000400080 <_start>:
  400080:       e8 e2 44 e3 00          call   1234567 <_end+0xc344df>

链接器计算出正确的rel32以达到0x1234567 from 0x400080+5,基于R_X86_64_PC32目标文件中的重定位:

  0:   e8 00 00 00 00          call   5 <_start+0x5>   1: R_X86_64_PC32        *ABS*+0x1234563

如何让 MASM 和/或 MSVC inline-asm 做到这一点?

MSVC 不接受_asm { call 1234567h; }。错误是C2415: improper operand type. 我找到的唯一答案 https://stackoverflow.com/questions/3933143/immediate-call-jmp-in-visual-c-inline-assembler建议使用内存或寄存器中的地址进行间接跳转的解决方法,但由于工具难以使用而导致机器代码效率低下并不是一个很好的解决方案。

我根本没有 MASM,所以我只能尝试 MSVC inline-asm (这不是同一件事)在 Godbolt 编译器资源管理器上 https://gcc.godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(j:1,lang:c%2B%2B,source:'void+foo()+%7B%0A+++//__asm+__emit++0xe8%0A+++//__asm+__emit++(0x00405B90+-+%24)%0A%0A+++_asm+%0A+++%7B%0A++++++call+0x00405B90%0A+++%7D%0A%7D'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),header:(),k:49.534686971235196,l:'4',m:100,n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:cl19_32,filters:(b:'0',binary:'0',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',trim:'1'),lang:c%2B%2B,libs:!(),options:'-Ox',source:1),l:'5',n:'0',o:'x86+MSVC+19+2017+RTW+(Editor+%231,+Compiler+%234)+C%2B%2B',t:'0')),k:50.465313028764804,l:'4',m:50,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(compiler:4,editor:1,wrap:'1'),l:'5',n:'0',o:'%234+with+x86+MSVC+19+2017+RTW',t:'0')),header:(),l:'4',m:50,n:'0',o:'',s:0,t:'0')),k:50.465313028764804,l:'3',n:'0',o:'',t:'0')),l:'2',n:'0',o:'',t:'0')),version:4.

您可以设置标签的地址并将其用作目标call symbol?就像气体一样.set symbol, 0x1234567它可以让你给一个符号一个地址without必须实际写作symbol:任何地方。

你可以直接发出编码吗db 0E8h / dd 1234567h - ($ + 4)?可能不会,在 NASM 中,仅适用于label - $ https://stackoverflow.com/questions/47494744/how-does-work-in-nasm-exactly, not absolute - label


我对答案最感兴趣,因此我可以将其包含在有关 jmp/call 绝对地址的规范答案中:在x86机器代码中调用绝对指针 https://stackoverflow.com/questions/19552158/call-an-absolute-pointer-in-x86-machine-code绝对不适合我想要实际使用的任何代码。


MASM 不支持这一点,因为 COFF 目标文件格式不支持必要的重定位。 (或者没有正确地支持吗?根据 NASM 错误消息。)

使用call 0x76cd75c0语法在nasm -f win32给出错误:

error: Win32 COFF does not correctly support relative references to absolute addresses

我不知道针对实模式平面二进制文件的 MASM 是否可以做到这一点(其中没有必须描述链接器重定位的目标文件),但不幸的是,MASM 可能只是在设计时根本没有语法。


也可以看看直接调用user32.dll中的函数时出错 https://stackoverflow.com/questions/53461451/error-when-calling-function-in-user32-dll-directly。我确实尝试过nasm -fwin322.13.02 我自己在我的 Linux 桌面上遇到了同样的错误。


未经测试的possible解决方法可能是创建一个.obj带有该绝对地址的符号定义,例如

org 0deadbeefH
global my_target
my_target:

在 NASM 中或者在 MASM 中执行此操作。

然后在 MASM 或 MSVC inline-asm 中你可以使用jmp my_target并与之链接.obj。理论上,这可以解决在目标文件中表示重定位的问题,并让链接器计算相对分支位移。

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

如何在 MASM 中为近直接相对调用/jmp 编写绝对目标 的相关文章

  • 在长模式下更改 GDT 并更新 CS

    我正在编写一个简单的自制 64 位操作系统 通过 UEFI 启动它 这意味着当我的代码开始执行时 它已经处于长模式 并且启用了分页 现在 退出 UEFI 引导服务后 我想用我自己的控制结构替换 UEFI 构建的所有控制结构 成功更改 CR3
  • g++ 内联汇编括号中不匹配

    g 向我抱怨以下代码中缺少括号 1 2 3 v v v asm volatile inb 1 0 a result Nd portnumber 1 2 3 正如您所看到的 括号是匹配
  • vs2010 C++ 尾调用优化

    考虑以下代码 int fac aux int x int res if x 1 return res else return fac aux x 1 res x int fac int x return fac aux x 1 int ma
  • Java用Rhino调用JS(未定义Uint8Array)

    我正在尝试使用 Rhino 库从 java 代码调用一些 javascript 但它似乎对类型化数组感到窒息 这是我的简单js文件 function decrypt version iv encryptedBuffer var output
  • 当非特权用户运行 C/asm 程序时,会对 Linux 造成什么危害?

    我一直在考虑一种场景 让用户 可以是任何人 可能有恶意 提交在 Linux PC 我们称之为基准节点 上运行的代码 目标是为单线程例程创建一种自动化基准测试环境 假设一个网站向代理发布了一些代码 该代理将此代码交给基准节点 而基准节点仅与代
  • gcc 如何知道内联汇编中使用的寄存器大小?

    我有内联汇编代码 define read msr index buf asm volatile rdmsr d buf 1 a buf 0 c index 使用该宏的代码 u32 buf 2 read msr 0x173 buf 我发现反汇
  • elf .rel.text 部分中 R_386_32/R_386_PC32 的含义

    为了理解重定位的概念 我编写了一个简单的 chk c 程序 如下所示 1 include
  • 推送 64 位 intel osx

    我想将 64 位地址压入堆栈 如下所示 asm pushq 0x1122334455667788 但我得到编译错误 我只能按以下方式推送 asm pushq 0x11223344 有人可以帮助我理解我的错误吗 我是装配新手 所以如果我的问题
  • “向量迭代器+偏移量超出范围”断言有用吗?

    这个完美的程序在 Visual Studio 2013 的调试模式下失败了 include
  • 自动创建 Visual C++ 故障转储

    有没有办法在应用程序崩溃时 在 Windows 操作系统上 自动创建故障转储文件 就像我可以使用附加的 Visual Studio 调试器进行保存一样 也就是说 我希望能够使用自动创建的故障转储文件在 Visual Studio 中调试我的
  • C/C++ 中的简单“Hello World”内联汇编语言程序

    我使用 devcpp 和 borland c 编译器 asm mov ax 4 I O Func mov bx 1 Output func mov cx name address of the string mov dx 6 length
  • 如何在 VC++ 中使用 _W64 和 __w64?

    有这样的事情 w64 http msdn microsoft com en us library s04b5w00 VS 71 aspx在 Visual C 9 中 我在尝试将本机 C DLL 移植到 64 位时遇到了它 特别是在crtde
  • 左/右旋转进位的实际用途

    循环左进位和循环右进位指令有哪些实际用途 在我的汇编课上 我们无法想出一个有用的好例子 如果要将位从一个操作数移出并移入另一个操作数 SHL EAX 1 move sign bit of EAX RCL EDX into LSB of ED
  • 使用 gdb 调试反汇编库

    在Linux和Mac OS X中可以使用strapi和next来调试应用程序而无需调试信息 在 Mac OS X 上 gdb 显示在库内部调用的函数 尽管有时会在每个 stepi 指令中推进多个汇编程序指令 在 Linux 上 当我进入动态
  • 在汇编中显示两位数? [复制]

    这个问题在这里已经有答案了 我对汇编编程完全陌生 在课堂作业的示例中 需要将两个数字相加并显示总和 我发现神秘的是当其是两位数时显示总和 这是我的代码 mov al num1 mov bl num2 add al bl add ax 303
  • 为什么这个 C++ 包装类没有被内联掉?

    EDIT 我的构建系统出了问题 我还在弄清楚到底是什么 但是gcc产生了奇怪的结果 尽管它是 cpp文件 但是一旦我使用了g 然后它按预期工作 对于我一直遇到麻烦的事情来说 这是一个非常精简的测试用例 其中使用数字包装类 我认为会内联 使我
  • 从 C++ 代码调用 Objective C 函数

    我用谷歌搜索了一下 找到了关于这个主题的一百万个结果 但这些页面都没有帮助我 我认为我有一个非常普遍的问题 我正在研究音频编程 特别是使用音频队列 我的程序的目的对于解释问题并不重要 但简而言之 当我尝试从 C 代码调用 Objective
  • 编译器优化导致性能下降

    我有一个奇怪的问题 我有以下代码 template
  • 如何在win32上安装OpenCV 2.0

    我需要在 Win32 上安装 OpenCV 我目前没有安装它 我下载了 OpenCV 2 0 0a win32 exe 并运行它 我现在到底该怎么办 没有 lib之类的东西 我找到了一些使用 cmake 构建版本的说明 http openc
  • 破坏/分解函数的函数

    我以前有过 here https stackoverflow com questions 4920610 c class function in assembly 已经表明 C 函数不容易用汇编表示 现在我有兴趣以一种或另一种方式阅读它们

随机推荐