【问题标题】:How can I move two dword into one qword?如何将两个 dword 移动到一个 qword 中?
【发布时间】:2016-11-24 03:30:38
【问题描述】:

我找到了类似的 anwser here,但它仅适用于 32 位。如何在 64 位处理器的 NASM 中做到这一点?

【问题讨论】:

  • 实际上我做不到,因为在做这样的事情时:mov eax, 1,它会覆盖整个 64 位的 rax。
  • 但是在做最后一件事时 -> mov ecx into eax, rax 中的前 4 个字节变成了 0
  • 正如我所说,不,他们没有,因为在 64 位中,当您将某些内容传递给 eax 时,前 4 个字节变为零。它不同于 32 位。
  • 没错,64位就是这样工作的。

标签: assembly nasm


【解决方案1】:

假设这是 X86,只需将低位 dword 放在第一位,高位 dword 放在第二位。我不确定nasm,但对于masm:

        .data
myqwrd  dd     089abcdefh, 001234567h         ;0123456789abcdef low first
; ...
        .code
        mov     eax, qword ptr myqwrd
;       or for immediate store
        mov     qword ptr myqwrd, 0fedcba9876543210h
;       or from ebx (low), ecx (high)
        mov     edx,ecx
        shl     rdx,32
        mov     eax,ebx
        or      rax,rdx

【讨论】:

  • mov qword ptr myqwrd, 0fedcba9876543210h 是不可能的。 mov r64, imm64, not r/m64 只能使用 64 位立即数。 IMO 只是通过显示一个示例来简化,该示例以 ECX 和 EDX 中的输入开始,并以 64 位寄存器中的结果结束,而不会弄乱内存。 IDK 如果您想提到需要使用 32 位 MOV 对函数 args 进行零扩展,以防它们包含大量垃圾,但将内存带入这只是一种干扰。
【解决方案2】:

您可以使用两个双字连续变量(一个接一个),分别为它们分配值,然后将两个值作为一个四字来获取。我在online compiler 中测试了下一个代码:

section .data
    dw1  : dd 0   ;◄■■ FIRST DOUBLE-WORD.
    dw2  : dd 0   ;◄■■ SECOND DOUBLE-WORD.

section .text
    global _start
_start:

    mov dword [dw2], 12345678h   ;◄■■ ONE DOUBLE-WORD.
    mov dword [dw1], 90ABCDEFh   ;◄■■ ANOTHER DOUBLE-WORD.
    mov rax, [dw1]               ;◄■■ GET ONE QUAD-WORD (1234567890ABCDEFh).

注意第二个双字(dw2)如何获得更高的值,而第一个双字(@987654327 @) 获取 较低的 值。还要注意四字是如何从第一个变量中提取的,但由于rax 的大小,它到达了第二个变量。

之前的代码没有显示任何内容来知道RAX 中发生了什么,所以这是我的原始代码:它将值从RAX 移动到一个字符串中,然后显示该字符串(垃圾字符):

section .data
    str1 : db  '12345678',10
    len  : equ $-str1
    dw1  : dd 0
    dw2  : dd 0

section .text
    global _start
_start:
    mov eax, 4
    mov ebx, 1
    mov ecx, str1
    mov edx, len
    int 80h             ;◄■■ DISPLAY STRING = "12345678".

    mov rax, 01234567890ABCDEFh ;◄■■ MOVE ONE QUAD-WORD DIRECTLY.
    mov [str1], rax    
    mov eax, 4
    mov ebx, 1
    mov ecx, str1
    mov edx, len
    int 80h             ;◄■■ DISPLAY STRING = "�ͫ�xV4"

    mov dword [dw2], 12345678h ;◄■■ MOVE ONE DOUBLE-WORD.
    mov dword [dw1], 90ABCDEFh ;◄■■ MOVE ANOTHER DOUBLE-WORD.
    mov rax, [dw1]
    mov [str1], rax    
    mov eax, 4
    mov ebx, 1
    mov ecx, str1
    mov edx, len
    int 80h            ;◄■■ DISPLAY STRING = "�ͫ�xV4" AGAIN!!!

    mov eax,1
    mov ebx,0
    int 80h

编辑: 上一个是“int 80h”版本,下一个是“系统调用版本”(感谢@MichaelPetch 告诉我我必须使用哪些寄存器),也在同一个@987654322 中进行了测试@:

section .data
    str1 : db  '12345678',10
    len  : equ $-str1
    dw1  : dd 0
    dw2  : dd 0

section .text
    global _start
_start:
    mov rax, 1
    mov rdi, 1
    mov rsi, str1
    mov rdx, len
    syscall             ;◄■■ DISPLAY STRING = "12345678".

    mov rax, 01234567890ABCDEFh ;◄■■ MOVE ONE QUAD-WORD DIRECTLY.
    mov [str1], rax    
    mov rax, 1
    mov rdi, 1
    mov rsi, str1
    mov rdx, len
    syscall             ;◄■■ DISPLAY STRING = "�ͫ�xV4"

    mov dword [dw2], 12345678h ;◄■■ MOVE ONE DOUBLE-WORD.
    mov dword [dw1], 90ABCDEFh ;◄■■ MOVE ANOTHER DOUBLE-WORD.
    mov rax, [dw1]
    mov [str1], rax    
    mov rax, 1
    mov rdi, 1
    mov rsi, str1
    mov rdx, len
    syscall            ;◄■■ DISPLAY STRING = "�ͫ�xV4" AGAIN!!!

    mov rax,60
    mov rdi,0
    syscall

【讨论】:

  • 不要在 64 位代码中使用 int 80h。它仍然是 32 位 ABI,因此它会截断任何指向 32 位的指针。例如,这意味着您不能传递堆栈指针。
  • 当然是 64 位 syscall ABI。系统调用号不同于 32 位 ABI,以及用于传递 args 的寄存器的顺序。 links in the x86 tag wiki.
  • syscall 指令没有操作数,syscall 数字在不同的寄存器中接受参数。
  • 我在 rextester 中尝试了syscall,它适用于简单的Hello World:rextester.com/VDVUNV32415
  • @MichaelPetch,天哪!你说的对。我测试了我的代码,但我使用的是相同的寄存器(我觉得很愚蠢)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
  • 2013-10-15
相关资源
最近更新 更多