- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
x86-64 SysV ABI 指定了如何在寄存器中传递函数参数(在 rdi
中的第一个参数,然后是 rsi
等),以及如何将整数返回值传回(在 rax
和然后 rdx
对于非常大的值)。
然而,我找不到的是,当传递小于 64 位的类型时,参数或返回值寄存器的高位应该是什么。
例如,对于以下函数:
void foo(unsigned x, unsigned y);
x
将在
rdi
中通过和
y
在
rsi
,但它们只有 32 位。做
rdi
的高32位和
rsi
必须为零?直觉上,我会假设是的,但是
code generated所有 gcc、clang 和 icc 都有特定的
mov
开始时的指令将高位清零,因此编译器似乎另有假设。
rax
如果返回值小于 64 位,则可能有垃圾位。例如,以下代码中的循环:
unsigned gives32();
unsigned short gives16();
long sum32_64() {
long total = 0;
for (int i=1000; i--; ) {
total += gives32();
}
return total;
}
long sum16_64() {
long total = 0;
for (int i=1000; i--; ) {
total += gives16();
}
return total;
}
clang
(和其他编译器类似):
sum32_64():
...
.LBB0_1:
call gives32()
mov eax, eax
add rbx, rax
inc ebp
jne .LBB0_1
sum16_64():
...
.LBB1_1:
call gives16()
movzx eax, ax
add rbx, rax
inc ebp
jne .LBB1_1
mov eax, eax
调用返回 32 位后,
movzx eax, ax
在 16 位调用之后 - 两者都分别具有将前 32 位或 48 位清零的效果。所以这种行为有一些成本——处理 64 位返回值的相同循环省略了这条指令。
uint32_t average(uint32_t a, uint32_t b) {
return ((uint64_t)a + b) >> 2;
}
average(unsigned int, unsigned int):
mov edi, edi
mov eax, esi
add rax, rdi
shr rax, 2
ret
ret
)来将高位清零。这在实践中使用移动消除可能很便宜,但似乎仍然需要付出很大的代价。
rdi
和
rsi
并且其他参数传递寄存器是临时的(即可以被调用者覆盖),您只有几种情况(我们查看
rdi
,但将其替换为您选择的参数 reg):
rdi
中的函数的值在调用后代码中已死(不需要)。在这种情况下,最后分配给 rdi
的任何指令只需分配给 edi
反而。这不仅是免费的,而且如果您避免使用 REX 前缀,它通常会小一个字节。 rdi
中的函数的值函数后需要。在那种情况下,由于 rdi
是调用者保存的,调用者需要做一个 mov
无论如何,被调用者保存的寄存器的值。您通常可以组织它,以便值从被调用者保存的寄存器中开始(比如 rbx
),然后移动到 edi
喜欢 mov edi, ebx
,所以不花钱。 rdi
的最后一条指令中需要 64 位数学运算。 .不过,这似乎很少见。
mov eax, eax
执行此操作的说明),但是如果允许垃圾,成本就会转移到被调用者身上。总的来说,调用者似乎更有可能免费清除垃圾,因此允许垃圾似乎总体上不会对性能产生不利影响。
short sums(short x, short y) {
return x + y;
}
int sumi(int x, int y) {
return x + y;
}
long suml(long x, long y) {
return x + y;
}
sum:
lea rax, [rdi+rsi]
ret
最佳答案
看起来你在这里有两个问题:
rax
的全部值(或
eax
)之后,这可能会导致信息泄漏。例如,一个系统调用可能会泄漏一个从内核到用户空间的指针,导致内核
ASLR失效。 .或
IPC机制可能会泄漏有关另一个进程的地址空间的信息,这有助于开发
sandbox爆发。
unsigned char buf[256];
...
__fastcall void write_index(unsigned char index, unsigned char value) {
buf[index] = value;
}
如果允许我们假设
index
将其高位清零,然后我们可以将上面的内容编译为:
write_index: ;; sil = index, dil = value
; movzx esi, sil ; skipped based on assumptions
mov [buf + rsi], dil
ret
但是如果我们可以从我们自己的代码中调用这个函数,我们可以提供一个值
rsi
出了
[0,255]
范围并写入超出缓冲区范围的内存。
movzx
指令。)
关于linux - x86-64 SysV ABI 中参数和返回值寄存器的高位是否允许垃圾?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40475902/
我无法理解如何使用一些旧的 VGA 代码在这个示例中设置序列 Controller 寄存器: mov dx,SC_INDEX mov ax,0604h out dx,ax
我希望对 zmm 0-31 寄存器集的四字元素执行整数算术运算并保留这些运算产生的进位位。看来这只有在通用寄存器集中处理数据时才有可能。 因此,我想将信息从 zmm 0-31 寄存器之一复制到通用寄存
ARM 64中包含多种寄存器,下面介绍一些常见的寄存器。 1 通用寄存器 ARM 64包含31个64bit寄存器,记为X0~X30。 每一个通用寄存器,它的低32bit都可以被访问,记为W0~W
1.寄存器 组合逻辑存在一个最大的缺点就是存在竞争与冒险,系统会产生不定态;使用时序逻辑电路就会极大的改善这种情况 寄存器具有存储功能,一般是由D触发器构成,由时钟脉冲控制,每个D触发器能够
使用 $gp 是否存在危险?注册以存储值?我想我的问题是 $gp 的真正功能是什么?它是否以某种方式在幕后调用,以便如果我使用它,事情可能会变得非常非常错误? 最佳答案 那么,$gp register
我遇到了这段代码的问题,我无法弄清楚问题出在哪里。所以当我运行这段代码时:if $row["count"] > 0 else块运行和 $_SESSION["error"]设置。 当$row["coun
所以我正在做二进制炸弹的变体。这就是阶段 0x0000000000401205 : sub $0x8,%rsp 0x0000000000401209 : cmp $0x3,
我在一个名为 (EmployeeDetailKey - varchar(10)) 的字段中获得了一个值,其中包含顺序值,例如 00001, 00002, 00003.... 它位于 Employeed
我有一个要求,应该为每个调用的线程分配一个计数器变量。但我没有得到预期的结果,实际上计数器在线程中重复。我创建了一个虚拟表和一个过程来将计数器值插入到表中。无论如何,是否可以更改代码以便线程获得递增的
预期输出:需要打印第4季度的wage_amt +--------------+--------------+--------------+--------------+ | wages_amt_q1
如何匹配模式 abc_[someArbitaryStringHere]_xyz? 为了澄清,我希望正则表达式能够匹配以下性质的字符串: abc_xyz、abc_asdfsdf_xyz、abc_32rw
从下拉列表(自定义)中选择一个值而不是常规下拉列表,它有很多下拉值 我可以用代码选择第一个值 find('.selected', :text=>arg1,exact: false).click 但无法
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我有 .csv 文件中的数据,它包含 2 列 x 轴和 y 轴。从 .csv 文件读取轴,然后使用拉伸(stretch)指数函数拟合数据,但显示错误。 这里我给出示例数据以方便理解。 我的函数是f(x
我正在尝试使用以下汇编代码将磁盘扇区加载到内存中,但正如我在终端中使用一些 int 0x10 时发现的那样,它不起作用的原因是它陷入了无限循环。我以为循环会自动为我递减 cx 寄存器。下面是代码,其中
我正在尝试编写一个脚本,该脚本将在 vim 中打开一个文件并将其中的特定行复制到 vim 的寄存器之一中。当脚本再次运行时,它会决定再次打开文件,然后将 vim 寄存器中的值粘贴回。实际上,脚本应该在
我目前正在尝试弄清楚如何将指针寄存器 SI 指向的内存中的第一个字节添加到 AX 寄存器的当前内容中。 因此,如果 SI 包含某个地址,并且该地址在内存中的值是:00 和 01,我希望将 00 添加到
我试图将两个 16 位数字与以下 NASM 代码相乘: mov ax, [input1] mov bx, [input2] mul bx 前面代码的结果存储在 DX:AX 我试图使用来自单独库“pri
我正在尝试修改 rip 寄存器(只是为了好玩)。 buffer 应该是内存地址,所以不知道为什么会得到Error: operand type mismatch for 'movq' #include
我可以告诉gcc-style inline assembly把我的__m512i变量到特定 zmm注册,如 zmm31 ? 最佳答案 就像在根本没有特定寄存器约束的目标(如 ARM)上一样,使用 lo
我是一名优秀的程序员,十分优秀!