- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 GAS 语法创建一个汇编程序,该程序可以在 x86-64 架构上以位置无关的方式访问 .data
部分中的变量,并强制执行 32bit arch 和 IS(%eip
而不是 %rip
)。
无论我尝试什么寄存器,我得到的最好结果都是段错误:11
,甚至这是为了访问我根本不应该能够执行的EIP,因此SF。最好的结果,因为这至少告诉我一些东西,而不是“嗯,这不行”。
我正在 macOS 10.13.6 mid 2010 Intel Core 2 Duo 上使用 gcc
编译该文件(这可能就是 clang
的原因):
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
并将一些选项传递给链接器:
gcc -m32 -Wl,-fatal_warnings,-arch_errors_fatal,-warn_commons,-pie test.s
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in _main from /whatever.../test-a07cf9.o. To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie ld: fatal warning(s) induced error (-fatal_warnings) clang: error: linker command failed with exit code 1 (use -v to see invocation) 1
测试.s
.text
.global _main
_main:
xor %eax, %eax
xor %ebx, %ebx
# lea var1(%esi/edi/ebp/esp), %ebx # can't compile, not PIE
# lea var1(%eip), %ebx # segfault, obvs
# lea (%esp), %ebx # EBX = 17
# lea (%non-esp), %ebx # segfault
# lea 0(%esi), %ebx # segfault
# lea 0(%edi), %ebx # segfault
# lea 0(%ebp), %ebx # EBX = 0
# lea 0(%esp), %ebx # EBX = 17
# lea 0(%eip), %ebx # segfault, obvs
movl (%ebx), %eax
ret
.data
var1: .long 6
.end
我正在使用 ./a.out 运行它; echo $?
检查最后 ret
中的 EAX 值。
我查看了各种来源,但主要是英特尔语法或以下问题之一 - 1 , 2 , 3 。我尝试反汇编我能想到的最简单的 C 示例,即全局变量 + 来自 main()
的 return
- gcc -S test.c -fPIE -饼-fpie-m32
:
int var1 = 6;
int main() { return var1; }
这基本上导致:
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 13
.globl _main ## -- Begin function main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushl %ebp
Lcfi0:
.cfi_def_cfa_offset 8
Lcfi1:
.cfi_offset %ebp, -8
movl %esp, %ebp
Lcfi2:
.cfi_def_cfa_register %ebp
pushl %eax
calll L0$pb
L0$pb:
popl %eax
movl $0, -4(%ebp)
movl _var1-L0$pb(%eax), %eax
addl $4, %esp
popl %ebp
retl
.cfi_endproc
## -- End function
.section __DATA,__data
.globl _var1 ## @var1
.p2align 2
_var1:
.long 6 ## 0x6
.subsections_via_symbols
这显然使用 MOV 作为 LEA,几乎与我的指令相同,除了 -L0$pb
部分应该是 +/- 类似 _var1
的地址 - L0$pb
进入 .data
部分。
然而,当我使用 var1
和 _main
标签尝试相同的方法时,什么也没有:
.text
.global _main
_main:
xor %eax, %eax
xor %ebx, %ebx
#movl var1-_main(%ebp), %eax # EAX = 191
#movl var1-_main(%esp), %eax # EAX = 204
#movl var1-_main(%eax), %eax # segfault
ret
.data
var1: .long 6
.end
有什么想法我做错了什么吗?
编辑:
我设法从反汇编的 C 示例中删除了所有不必要的内容,最后得到了这个:
.text
.global _main
_main:
pushl %ebp
pushl %eax
calll test
test:
popl %eax
/* var1, var2, ... */
movl var1-test(%eax), %eax
addl $4, %esp
popl %ebp
retl
/**
* how var1(label) - test(label) skips this label
* if it's about address subtracting?
*/
blobbbb:
xor %edx, %edx
.data
var1: .long 6
var2: .long 135
这对我来说没有多大意义,因为根据 this guide调用者应该 1) 将参数压入堆栈(无) 2) call
标签,并且被调用者应该实际使用 ESP、EBP和其他寄存器。另外,为什么我需要一个中间标签,或者更好地说,有没有办法不需要它?
最佳答案
在 32 位模式中,没有 64 位模式中那样的 eip
相对寻址模式。因此,代码如下
mov var(%eip), %eax
实际上并不合法,并且不能在 32 位模式下进行汇编。 (在 64 位中,它将把地址截断为 32 位)。在传统的非 PIE 32 位二进制文件中,您只需这样做
mov var, %eax
它将 var
的绝对地址处的值移动到 eax
,但这在 PIE 二进制文件中是不可能的,因为 var
的绝对地址在链接时未知。
链接器所知道的是二进制文件的布局以及标签之间的距离是多少。因此,要访问全局变量,您可以像这样进行:
var
的距离可以使用带有位移的寻址模式来组合步骤 2 和 3。第 1 步很棘手。只有一条有用的指令可以告诉我们一个我们不知道其地址的位置的地址是什么,那就是 call
:call
指令推送下一个位置的地址指令入栈,然后跳转到指定地址。如果我们告诉call
只跳转到下一个地址,我们就会将其功能减少到本质上push %eip
:
call Label # like push %eip
Label: ...
请注意,此用例在 CPU 的返回预测中是特殊情况,实际上并不算作函数调用。由于这不是真正的函数调用,因此我们没有建立堆栈帧或类似的框架,并且我们没有此调用的返回。它只是一种获取指令指针值的机制。
由此,我们知道了Label
的地址。接下来我们可以将其从堆栈中弹出并使用它来查找 var
的地址:
call Label
Label: pop %eax # eax = Label
add $var-Label, %eax # eax = Label + var - Label = var
然后我们可以取消引用它来获取var
的内容:
call Label
Label: pop %eax
add %eax, $var-Label
mov (%eax), %eax # eax = *var
在实际代码中,您可以合并加法和内存操作数以保存指令:
call Label
Label: pop %eax
mov var-Label(%eax), %eax # eax = *var
如果你想在一个函数中引用多个静态变量,你只需要使用这个技巧一次。只需使用适当的差异:
call Label
Label: pop %eax
mov foo-Label(%eax), %ebx # ebx = *foo
mov bar-Label(%eax), %ecx # ecx = *bar
请注意,gcc 支持此习惯用法的变体来获取指令指针的内容。它创建了一堆像这样的函数:
___x86.get_pc_thunk.bx:
mov (%esp), %ebx
ret
将返回地址移动到指定的寄存器。这是一个特殊函数,不遵循正常的调用约定,eax
、ebx
、ecx
、edx 各存在一个函数
、esi
和 edi
,具体取决于 gcc 要使用的寄存器。代码如下所示:
call ___x86.get_pc_thunk.bx # ebx = Label
Label: mov foo-Label(%ebx), %eax # eax = *foo
mov bar-Label(%ebx), %ecx # ecx = *bar
gcc 使用此代码在返回预测不考虑此假调用习惯用法的 CPU 上获得更好的性能。但我不知道哪些 CPU 实际上受到了影响。
最后请注意,没有跳过任何标签。我不太明白您对 blobbbb
的意思。哪个控件应该达到这个标签?
最后,您的示例应如下所示:
.text
.global _main
_main: call Label # push %eip
Label: pop %eax # eax = Label
mov var1-Label(%eax), %eax # eax = *(Label+var1-Label)
ret
.data
var1: .long 6
请注意,永远不需要 .end
指令。以大写 L
开头的标签是本地标签,不会出现在符号表中,这就是 C 编译器喜欢使用它们的原因。
关于assembly - GAS ASM PIE x86-64 使用 LEA 指令访问变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52344336/
我正在使用松露部署合约,当我将气体限制指定为我想要用于交易的气体时,我总是会收到超出气体限制的错误。为什么会出现这种情况? 编辑我想做的是将加密小猫 KittyCore.sol 合约部署到我的本地开发
我正在获取不属于自己的代币的 ERC721 转移。有什么帮助吗? 未处理的拒绝(错误):无法估计气体;交易可能会失败或可能需要手动 gas 限制(error={"code":-32603,"messa
我正在使用 Mogsdad here 发布的增强工作流程脚本. 我已经设法解决了一些问题,但目前我遇到的一个问题是本节中出现的错误 - // Record approval or rejection
我让这个函数循环遍历所有工作表,如果工作表未隐藏,则将工作表名称添加到数组 out 中。 function sheetnames() { var sheets = SpreadsheetApp.g
在我的 html 代码中,我调用一个脚本来编辑 Google 表单,然后加载该表单。我的问题是,网页在脚本更新完成之前加载。 google.script.run.c
我需要构建iOS的OpenBLAS库。我选择构建它的 0.3.6 版本。我相信这是该库最新的稳定版本。 您可以在此处找到该库的版本 - https://github.com/xianyi/OpenBL
我正在使用 ganache 创建 10 个以太坊账户。我想将以太坊从一个账户转移到一个智能合约。我通过编写以下两个可靠的智能合约来做到这一点; pragma solidity >=0.4.0 {
我的脚本有时有效,有时会出错。运行调试显示我的 array.sort 可能是问题所在。这是错误: We're sorry, a server error occurred. Please wait a
我目前正在为我工作的公司的分支机构构建一个 Google 网站。作为该网站的一部分,我们有一个托管 Web 应用程序的页面,该应用程序在访问时会获取当前用户的 ID,并使用 JavaScript
Google Apps 脚本支持 Triggers ,那个通行证Events触发功能。不幸的是,开发环境将允许您在不传递参数的情况下测试函数,因此您不能以这种方式模拟事件。如果您尝试,您会收到如下错误
除非我使用 .toLocaleDateString() 方法,否则下面的函数返回的日期比应有的日期少一天。我做错了什么或者这是一个缺陷? function myDate() { var s
嗨,我有以下汇编代码, .export __ls__11NSDOM_EncapFf .text __ls__11NSDOM_EncapFf: /* first load the symbolic co
我试图在不同的侧边栏中调用另一个侧边栏,以在谷歌文档中创建一种选项卡式界面。我不知道如何调用在当前侧边栏的 html 文件中显示新侧边栏的服务器端函数。 这是我的 html 侧边栏按钮布局...(不起
我刚刚开始使用 GAS,所以如果这是一个明显的问题,我将不胜感激任何见解并道歉。我正在尝试实现一个日期选择器,以便用户可以选择一些日期而不是输入它们。我使用此问题中的代码来执行此操作: Returni
Google Apps 脚本支持 Triggers ,即通过Events来触发功能。不幸的是,开发环境将允许您测试没有参数传递的函数,因此您无法以这种方式模拟事件。如果您尝试,您会收到如下错误: Re
我想显示来自 GAS 的数据并自动显示电子表格中每个单元格的数据。我尝试了“appendRow”,但出现错误(超过 2000000 个单元格)。如果我可以“appendRow”,请告诉我。 现在,我尝
GAS 初学者遇到了从 Google Apps 脚本循环中检索所有条件匹配值的问题。 我的电子表格中的一列有日期。条件运算符if (formattedCheckInDate == formattedT
我需要将函数传递的值(例如 20.35)添加到每个选定的单元格。我有一个巨大的列表,下面的函数超时,最多可以运行 6 分钟而无法将添加的结果添加到单元格 如何实现一种解决方法,以便每次在完成计算后立即
似乎有很多关于此的问题,但没有一个完全符合我的需求。 我使用的是 GAS,它不接受正则表达式lookbehind。 我有下面的正则表达式,它应该匹配第五个字符后的 :00。因此忽略前 5 个字符,无论
我有一个 Google App Script Code 代码,要求用户通过 html 自定义对话框输入一些值。对话框中的按钮触发 .gs 文件中的一个函数,我想等待该触发的函数返回,然后再继续其余代码
我是一名优秀的程序员,十分优秀!