相关疑难解决方法(0)

在x86汇编中将64位常量移动到内存

我正在使用Intel x64汇编,NASM编译器,尝试将"0x4000000000000000"常量移动到内存,在ieee 754标准double中应该等于2.0.

我正在使用的代码是:

%define two 0x4000000000000000 

section .text

foo:

push rbp
mov rbp, rsp

mov QWORD [rdi], two

pop rbp
ret
Run Code Online (Sandbox Code Playgroud)

编译此抛出

警告:签名dword立即超出界限.

当我用C++打印值时,它显示"0"而不是"2".

我已经找到了获得正确价值的方法,即:

mov r9, 0x4000000000000000
mov [rdi], r9
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有办法在不使用寄存器的情况下实现这一目标.

顺便说一句,我用这个脚本编译代码:

#!/bin/bash
nasm -f elf64 -g -F dwarf vvp_asm.asm -o vvp_asm.o
g++ -c -m64 -std=c++11 main.cpp -o main.o
g++ -o main -m64 vvp_asm.o main.o
Run Code Online (Sandbox Code Playgroud)

64-bit x86 assembly x86-64 nasm

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

为什么 Linux 上的 NASM 会更改 x86_64 程序集中的寄存器

我是 x86_64 汇编编程的新手。我正在用 x86_64 程序集编写简单的“Hello World”程序。下面是我的代码,它运行得很好。

global _start

section .data

    msg: db "Hello to the world of SLAE64", 0x0a
    mlen equ $-msg

section .text
    _start:
            mov rax, 1
            mov rdi, 1
            mov rsi, msg
            mov rdx, mlen
            syscall

            mov rax, 60
            mov rdi, 4
            syscall 
Run Code Online (Sandbox Code Playgroud)

现在,当我在 gdb 中反汇编时,它会给出以下输出:

(gdb) disas
Dump of assembler code for function _start:
=> 0x00000000004000b0 <+0>:     mov    eax,0x1
   0x00000000004000b5 <+5>:     mov    edi,0x1
   0x00000000004000ba <+10>:    movabs rsi,0x6000d8
   0x00000000004000c4 <+20>:    mov    edx,0x1d
   0x00000000004000c9 <+25>:    syscall
   0x00000000004000cb <+27>:    mov …
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 nasm micro-optimization shellcode

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

为什么我们不能将 64 位立即数移动到内存中?

首先,我对movq和之间的区别有点困惑movabsq,我的教科书说:

常规movq指令只能具有可以表示为 32 位二进制补码的立即数源操作数。然后对该值进行符号扩展以生成目标的 64 位值。所述movabsq指令可以具有任意的64位立即值作为其源操作数,并且只能有一个寄存器作为目的地。

我有两个问题。

问题 1

movq指令只能具有可以表示为 32 位二进制补码的立即数源操作数。

所以这意味着我们不能做

movq    $0x123456789abcdef, %rbp
Run Code Online (Sandbox Code Playgroud)

我们必须这样做:

movabsq $0x123456789abcdef, %rbp
Run Code Online (Sandbox Code Playgroud)

但是为什么movq被设计为不适用于 64 位立即数,这确实违背了q(四分字)的目的,我们需要movabsq为此目的而设置另一个,这不是很麻烦吗?

问题2

由于目标movabsq必须是寄存器,而不是内存,所以我们不能将 64 位立即数移动到内存中:

movabsq $0x123456789abcdef, (%rax)
Run Code Online (Sandbox Code Playgroud)

但有一个解决方法:

movabsq $0x123456789abcdef, %rbx
movq    %rbx, (%rax)   // the source operand is a register, not immediate constant, and the destination of movq can be memory
Run Code Online (Sandbox Code Playgroud)

那么为什么这条规则旨在让事情变得更难呢?

assembly x86-64 instruction-set cpu-architecture immediate-operand

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

x86 64汇编

我正在编写一个自修改代码.

movq      $TARGET_CIA, 0x550(%rax)
Run Code Online (Sandbox Code Playgroud)

此符号TARGET_CIA最初未定义,在运行时我尝试将64位立即值复制到此位置.但是在编译时,该指令将此未定义立即值的值取为32位,当我尝试复制64位时,我看到有符号扩展的32位.有没有办法让这个未定义的符号被视为64位值?

assembly x86-64

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

您如何理解 x86-64 汇编的“REX.W + B8+ rd io”形式?

我最初试图生成立即移动到 64 位寄存器的字节。我想要的具体操作是

mov rdi, 0x1337
Run Code Online (Sandbox Code Playgroud)

使用https://www.felixcloutier.com/x86/mov,我看到的唯一非符号扩展指令是

REX.W + B8+ rd io
Run Code Online (Sandbox Code Playgroud)

这让我很困惑,所以我创建了一个小型汇编程序来查看汇编器会生成什么

          global    _start

          section   .text
_start:   
          mov       rdi, 0x1337 
          syscall                           
          mov       rax, 60                 
          xor       rdi, rdi                
          syscall                           
Run Code Online (Sandbox Code Playgroud)

我必须关闭优化,以便迁移到 64 位寄存器。所以我编译nasm -felf64 -O0 main.asm && ld main.o并生成了一个a.out. 我看着objdump -M intel -d ./a.out这行

48 bf 37 13 00 00 00    movabs rdi,0x1337  
Run Code Online (Sandbox Code Playgroud)

那条线看起来一点也不像

REX.W + B8+ rd io
Run Code Online (Sandbox Code Playgroud)

大部头书?另外,经过一些研究,我发现该命令应该是 10 个字节。你如何从 得到它REX.W + B8+ rd io

assembly x86-64 nasm machine-code instruction-encoding

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

Push/Pop 与使用寄存器的 Move 比较

在 x86_64 中(在 Linux 上使用 nasm 进行组装),我的直觉告诉我,rax在 (1) 和 (2) 之后会有相同的内容。

push qword 11               ; (1) Works!
pop rax

;mov rax, qword 11          ; (2) Doesn't Work!
Run Code Online (Sandbox Code Playgroud)

但是(1)工作得很好,(2)使我的程序出现段错误。这里发生了什么?

x86 assembly nasm

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

MOV r/m32、imm32 和 MOV r32、imm32 之间的操作码差异

这些是MOV来自Intel\xc2\xae 64 和 IA-32 架构软件开发人员手册的指令操作码:

\n

B8+ rd id MOV r32, imm32 OI Valid Valid Move imm32 to r32

\n

C7 /0 id MOV r/m32, imm32 MI Valid Valid Move imm32 to r/m32

\n

我拆解如下:

\n
0:  b8 44 33 22 11          mov    eax, 0x11223344\n
Run Code Online (Sandbox Code Playgroud)\n
0:  67 c7 00 44 33 22 11    mov    DWORD PTR[eax], 0x11223344\n
Run Code Online (Sandbox Code Playgroud)\n

我想问的问题是:

\n
    \n
  • 为什么C7操作码是寄存器/内存(r/m32, imm32)而不是仅内存(m32, imm32)?

    \n
  • \n
  • 是否有任何时候我们使用 …

assembly x86-64 machine-code opcode instruction-encoding

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

x86_64 无法将 64 位值添加到 rax,“'add' 上的操作数不匹配”

我正在尝试组装一些 64 位代码,但组装失败了:

addq $0xffffff7fc0005000, %rax
Run Code Online (Sandbox Code Playgroud)

有错误:

`add' 的错误操作数类型不匹配

第一个操作数是一个 64 位值,后者是一个应该组装好的寄存器。该指令前面有一个.code64伪操作。我正在组装

x86_64-elf-as test.s -o test.o --64
Run Code Online (Sandbox Code Playgroud)

至于汇编器本身,当用--version它调用时返回:

GNU assembler (GNU Binutils) 2.32
Copyright (C) 2019 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `x86_64-elf'.
Run Code Online (Sandbox Code Playgroud)

assembly x86-64 gnu-assembler immediate-operand

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