相关疑难解决方法(0)

使用下半部分后取消引用64位寄存器

我有一个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的下半部分.如果任何人有任何关于正确使用寄存器下部的信息的链接/参考,我也将不胜感激.

非常感谢你的帮助.

assembly x86-64

2
推荐指数
1
解决办法
574
查看次数

了解 libc.a 中的简单 Linux 系统调用

我正在使用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 行代码做了什么?

linux assembly x86-64 system-calls

2
推荐指数
1
解决办法
645
查看次数

汇编程序何时更好地使用符号扩展重定位(如R_X86_64_32S)而不是像R_X86_64_32那样的零扩展?

作为一个具体的例子,在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

assembly x86-64 gnu-assembler nasm elf

2
推荐指数
1
解决办法
398
查看次数

使用 x64 汇编代码的基本输入

我正在编写有关汇编中基本输入和输出的教程。我使用的是 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)

linux io assembly x86-64 nasm

2
推荐指数
2
解决办法
3318
查看次数

除以负数让我在 NASM 中溢出

我正在自学一些使用 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)

assembly x86-64 nasm

2
推荐指数
1
解决办法
1264
查看次数

为什么我们不能直接从堆栈帧移1个字节到寄存器?

我正在阅读《计算机系统:程序员的观点》,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)

assembly gcc x86-64 calling-convention function-parameter

2
推荐指数
1
解决办法
64
查看次数

源操作数和目标操作数是否需要相同大小?

我刚刚尝试了这个问题,要求你解释一下代码行有什么问题:

movl %eax, %rdx
Run Code Online (Sandbox Code Playgroud)

解决方案表明目标操作数的大小错误。

仅当从较大尺寸变为较小尺寸时才“非法”,还是源操作数和目标操作数对于所有指令(或至少 mov 类类型)必须具有相同的尺寸?

x86 assembly x86-64

2
推荐指数
1
解决办法
562
查看次数

为什么使用xor而不是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个字节。

两种方式如何运作?为什么第一个字节比第二个字节少?

assembly x86-64 machine-code code-size

1
推荐指数
1
解决办法
96
查看次数

为什么在 64 模式下默认操作数大小为 32 位?

我正在阅读英特尔文档,第一卷。1 和3.6.1 64 位模式下的操作数大小和地址大小一章。有三个前缀REX.W,操作数大小66和地址大小67前缀。并提到操作数的大小默认为 32 位。并且只能用REX.W指令前缀(在其他前缀之后)以使其长度为 64 位。

我不知道为什么会这样,为什么我不能将完整的 64 位空间用于例如int操作数?跟签有关系吗?或者为什么会有这个限制?(所以,C是否在 int 上unsigned int使用REX.W前缀操作(正如也提到的,前缀仅持续特定指令,而不是整个段,这应该是(大小,地址或操作数)默认值和包含在段描述符中)。

我理解正确吗?

64-bit assembly x86-64 machine-code instruction-encoding

1
推荐指数
1
解决办法
621
查看次数

为什么在数据类型为 64 位时使用 32 位寄存器?

我正在阅读一本教科书,其中有一个基于 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

1
推荐指数
1
解决办法
180
查看次数