我正在使用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) 我是 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) 首先,我对movq和之间的区别有点困惑movabsq,我的教科书说:
常规movq指令只能具有可以表示为 32 位二进制补码的立即数源操作数。然后对该值进行符号扩展以生成目标的 64 位值。所述movabsq指令可以具有任意的64位立即值作为其源操作数,并且只能有一个寄存器作为目的地。
我有两个问题。
该movq指令只能具有可以表示为 32 位二进制补码的立即数源操作数。
所以这意味着我们不能做
movq $0x123456789abcdef, %rbp
Run Code Online (Sandbox Code Playgroud)
我们必须这样做:
movabsq $0x123456789abcdef, %rbp
Run Code Online (Sandbox Code Playgroud)
但是为什么movq被设计为不适用于 64 位立即数,这确实违背了q(四分字)的目的,我们需要movabsq为此目的而设置另一个,这不是很麻烦吗?
由于目标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
我正在编写一个自修改代码.
movq $TARGET_CIA, 0x550(%rax)
Run Code Online (Sandbox Code Playgroud)
此符号TARGET_CIA最初未定义,在运行时我尝试将64位立即值复制到此位置.但是在编译时,该指令将此未定义立即值的值取为32位,当我尝试复制64位时,我看到有符号扩展的32位.有没有办法让这个未定义的符号被视为64位值?
我最初试图生成立即移动到 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?
在 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)使我的程序出现段错误。这里发生了什么?
这些是MOV来自Intel\xc2\xae 64 和 IA-32 架构软件开发人员手册的指令操作码:
B8+ rd id MOV r32, imm32 OI Valid Valid Move imm32 to r32。
C7 /0 id MOV r/m32, imm32 MI Valid Valid Move imm32 to r/m32。
我拆解如下:
\n0: b8 44 33 22 11 mov eax, 0x11223344\nRun Code Online (Sandbox Code Playgroud)\n0: 67 c7 00 44 33 22 11 mov DWORD PTR[eax], 0x11223344\nRun Code Online (Sandbox Code Playgroud)\n我想问的问题是:
\n为什么C7操作码是寄存器/内存(r/m32, imm32)而不是仅内存(m32, imm32)?
是否有任何时候我们使用 …
我正在尝试组装一些 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)