我有一个64位寄存器,它保存一个存储器地址.如果我对寄存器的下半部分执行算术运算然后尝试取消引用它,我会得到一个分段错误.这是一个例子:
movsx rax, BYTE PTR [rdi] # ok
add edi, 1 # the address is correct but....
movsx rax, BYTE PTR [rdi] # segmentation fault here
Run Code Online (Sandbox Code Playgroud)
如果我在第2行将edi更改为rdi,那么我只是想知道为什么在这种情况下我不能使用rdi的下半部分.如果任何人有任何关于正确使用寄存器下部的信息的链接/参考,我也将不胜感激.
非常感谢你的帮助.
我正在使用glibc-2.13-1运行64 位 Debian 4.7.2-5 Linux系统。当我在搜索一些函数调用的汇编代码时,我遇到了这个:libc.a
file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <sync>:
0: b9 a2 00 00 00 mov eax,0xa2
5: 0f 05 syscall
7: 48 3d 01 f0 ff ff cmp rax,0xfffffffffffff001
d: 0f 83 00 00 00 00 jae 13 <sync+0x13>
13: c3 ret
Run Code Online (Sandbox Code Playgroud)
我对这是做什么感到有点困惑。如果这是一台 64 位机器(系统调用如何知道要进行什么系统调用),有什么意义mov eax,0xa2以及为什么不使用rax寄存器?简而言之:这 5 行代码做了什么?
作为一个具体的例子,在GAS 2.24上移动地址:
mov $s, %eax
s:
Run Code Online (Sandbox Code Playgroud)
后:
as --64 -o a.o a.S
objdump -Sr a.o
Run Code Online (Sandbox Code Playgroud)
使用零扩展:
0000000000000000 <s-0x5>:
0: b8 00 00 00 00 mov $0x0,%eax
1: R_X86_64_32 .text+0x5
Run Code Online (Sandbox Code Playgroud)
但内存访问:
mov s, %eax
s:
Run Code Online (Sandbox Code Playgroud)
编译以签署扩展名:
0000000000000000 <s-0x7>:
0: 8b 04 25 00 00 00 00 mov 0x0,%eax
3: R_X86_64_32S .text+0x7
Run Code Online (Sandbox Code Playgroud)
在这种特定情况下,或者一般情况下,是否有理由使用?我不明白汇编程序如何能够对任何一种情况做出更好的假设.
NASM 2.10.09仅R_X86_64_32用于上述两种情况.更新:在2.11之后的一个边缘nasm commit 6377180产生相同的Gas输出,这看起来像Ross提到的一个bug.
我已经解释了我认为我理解的内容R_X86_64_32S:https://stackoverflow.com/a/33289761/895245
我正在编写有关汇编中基本输入和输出的教程。我使用的是 64 位的 Linux 发行版 (Ubuntu)。在教程的第一部分,我谈到了基本输出并创建了一个简单的程序,如下所示:
global _start
section .text
_start:
mov rax,1
mov rdi,1
mov rsi,message
mov rdx,13
syscall
mov rax,60
xor rdi,rdi
syscall
section .data
message: db "Hello, World", 10
Run Code Online (Sandbox Code Playgroud)
这很好用。系统打印字符串并干净地退出。对于教程的下一部分,我只想从键盘读取一个字符。根据我对这个网站的理解,我们将rdi寄存器更改为0以进行 sys_read 调用。
我首先从当前rsp 中减去 8 ,然后将该地址加载到rsi寄存器中。(那是我想存储字符的地方)。当我编译并运行我的程序时,它似乎可以工作……但终端似乎模仿了我再次输入的输入。
这是程序:
global _start
section .text
_start:
sub rsp,8 ; allocate space on the stack to read
mov rdi,0 ; set rdi to 0 to indicate a system read
mov rsi,[rsp-8]
mov …Run Code Online (Sandbox Code Playgroud) 我正在自学一些使用 x86-64 Mac OS 的汇编编程。我试图弄清楚为什么在将正整数除以负整数时会溢出。例如,5/-2必须返回-2。但是,就我而言,它2147483371在我执行时返回 a-554/2而不是-277...这是我的程序集文件中的内容:
; compiling using: nasm -f macho64 -o divide.o divide.s
[bits 64]
global _divide
section .text
; int divide(int dividend, int divisor)
_divide:
xor rdx, rdx ; making this to 0
push rbp ; base stack pointer
mov rax, rdi ; dividend
mov rcx, rsi ; divisor
idiv rcx ; integer division
add rsp, 8
ret
Run Code Online (Sandbox Code Playgroud)
在我的main.c文件中,我有这个:
#include <stdio.h>
extern int divide(int dividend, …Run Code Online (Sandbox Code Playgroud) 我正在阅读《计算机系统:程序员的观点》,3 / E(CS:APP3e)Randal E. Bryant和David R. O'Hallaron,作者说:“观察到第6行的movl指令从内存中读取了4个字节;以下addb指令仅使用低位字节”
第6行,为什么使用movl?他们为什么不移动8(%rsp),%dl?
void proc(a1, a1p, a2, a2p, a3, a3p, a4, a4p)
Arguments passed as follows:
a1 in %rdi (64 bits)
a1p in %rsi (64 bits)
a2 in %edx (32 bits)
a2p in %rcx (64 bits)
a3 in %r8w (16 bits)
a3p in %r9 (64 bits)
a4 at %rsp+8 ( 8 bits)
a4p at %rsp+16 (64 bits)
1 proc:
2 movq 16(%rsp), %rax Fetch a4p (64 bits)
3 addq %rdi, (%rsi) *a1p += a1 (64 …Run Code Online (Sandbox Code Playgroud) 我刚刚尝试了这个问题,要求你解释一下代码行有什么问题:
movl %eax, %rdx
Run Code Online (Sandbox Code Playgroud)
解决方案表明目标操作数的大小错误。
仅当从较大尺寸变为较小尺寸时才“非法”,还是源操作数和目标操作数对于所有指令(或至少 mov 类类型)必须具有相同的尺寸?
当将x设置为零(x = 0)时,我的csapp书指出了两种方法。
第一:
xorq %rcx, %rcx
Run Code Online (Sandbox Code Playgroud)
第二:
movq $0, %rcx
Run Code Online (Sandbox Code Playgroud)
它还表明第一个仅占用3个字节,而第二个仅占用7个字节。
两种方式如何运作?为什么第一个字节比第二个字节少?
我正在阅读英特尔文档,第一卷。1 和3.6.1 64 位模式下的操作数大小和地址大小一章。有三个前缀REX.W,操作数大小66和地址大小67前缀。并提到操作数的大小默认为 32 位。并且只能用REX.W指令前缀(在其他前缀之后)以使其长度为 64 位。
我不知道为什么会这样,为什么我不能将完整的 64 位空间用于例如int操作数?跟签有关系吗?或者为什么会有这个限制?(所以,C是否在 int 上unsigned int使用REX.W前缀操作(正如也提到的,前缀仅持续特定指令,而不是整个段,这应该是(大小,地址或操作数)默认值和包含在段描述符中)。
我理解正确吗?
我正在阅读一本教科书,其中有一个基于 C 代码生成汇编代码的练习:
代码:
long arith(long x, long y, long z)
{
long t1 = x ^ y;
long t2 = z * 48;
long t3 = t1 & 0x0F0F0F0F;
long t4 = t2 - t3;
return t4;
}
Run Code Online (Sandbox Code Playgroud)
汇编代码:
//x in %rdi, y in %rsi, z in %rdx
arith:
xorq %rsi, %rdi //t1 = x ^ y
leaq (%rdx,%rdx,2), %rax //3*z
salq $4, %rax //t2 = 16 * (3*z) = 48*z
andl $252645135, %edi //t3 = t1 & 0x0F0F0F0F …Run Code Online (Sandbox Code Playgroud) assembly bit-manipulation x86-64 instruction-set instructions
assembly ×10
x86-64 ×10
nasm ×3
linux ×2
machine-code ×2
64-bit ×1
code-size ×1
elf ×1
gcc ×1
instructions ×1
io ×1
system-calls ×1
x86 ×1