Я нашел аналогичный ответ здесь, но это работает только для 32bit. Как я могу сделать это в NASM на 64-битном процессоре?
Как я могу переместить два двойных слова в одно qword?
- На самом деле я не могу, потому что, делая что-то вроде этого: mov eax, 1, он переопределяет весь rax в 64-битной версии. 22.11.2016
- Но при выполнении последнего действия - › перемещение ecx в eax, первые 4 байта в rax становятся 0 22.11.2016
- Как я уже сказал, нет, потому что в 64-битной системе, когда вы что-то передаете в eax, первые 4 байта становятся равными нулю. Он отличается от 32-битного. 22.11.2016
- Именно так работает 64бит. 22.11.2016
Ответы:
Предполагая, что это X86, просто поместите сначала двойное слово младшего порядка, а затем — старшее двойное слово. Насчет 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
Вы можете использовать две последовательные переменные из двойного слова (одну за другой), присвоить им значения по отдельности, а затем получить оба значения как одно четверное слово. Я протестировал следующий код в этом онлайн-компиляторе:
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
) получает более высокое значение, а первое двойное слово (dw1
) получает меньшее значение. Также обратите внимание, как четверное слово извлекается из первой переменной, но достигает второй переменной из-за размера 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 за то, что рассказал мне, какие регистры мне пришлось использовать), также протестирована в том же онлайн-компилятор :
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
int 80h
в 64-битном коде. Это по-прежнему 32-битный ABI, поэтому он усекает любые указатели на 32-битные. Это означает, что вы, например, не можете передавать указатели стека. 23.11.2016 syscall
ABI. Номера системных вызовов отличаются от 32-битного ABI, а также порядок регистров, используемых для передачи аргументов. ссылки на вики тегов x86. 23.11.2016 syscall
не имеет операндов, а числа syscall
принимают параметры в разных регистрах. 23.11.2016 syscall
в rextester, и это сработало для простого Hello World
: rextester.com/VDVUNV32415 23.11.2016 int 0x80
из 64-битного кода. Это просто плохой пример, которому никто не должен следовать. Конечно, IDK делает системные вызовы, связанные с объединением двух двойных слов... Похоже, это добавляет много кода, который не имеет отношения к проблеме. 24.11.2016 rax
контента. 24.11.2016
mov qword ptr myqwrd, 0fedcba9876543210h
невозможно. Вы можете использовать только 64-битные непосредственные ссылки сmov r64, imm64
, а неr/m64
. IMO просто упростит, показав пример, который начинается с ввода в ECX и EDX и заканчивается результатом в 64-битном регистре, не возясь с памятью. IDK, если вы хотите упомянуть о необходимости нулевого расширения аргументов функции с 32-битным MOV на случай, если они содержат много мусора, но привлечение памяти в это просто отвлекает. 24.11.2016