Moving Data
Before going ahead, here are three rules:
a) In 64-bit mode, operands generate a 64-bit result in the destination GP register b) In 32-bit mode, operands generate a 32-bit result, zero-extended to a 64-bit result in the destination general purpose register c) In 8-bit and 16-bit mode, operands generate an 8 or 16 bit result. The upper 56 or 48 bits of the GPR are untouched d) If the result of an 8 or 16-bit operation is intended for 64-bit address calculation, explicitly sign-extend the register to the full 64-bits.
"Zero extended"??? We'll talk about this after introducing a few operands that are used to move data in assembly.
MOV instruction
MOV is the most common instruction in assembly. It allows data moving in the following formats:
Between registers
Memory to registers and Registers to Memory
Immediate data to registers
Immediate data to memory
LEA
LEA=> Load Effective Address.
It loads pointer values in registers
Eg: LEA RAX, [var1]
Where var1 is the label given to any data type (talked in data type article here: https://hexisanoob.gitbook.io/hexisanoob/application-security/linux-64-bit-assembly/data-types)
Please note that, these two instructions essentially mean the same thing:
mov rax, sample
lea rax,[sample]
XCHG
Swaps values in between:
Register and Register: XCHG RAX, RBX
Register and Memory: XCHG RAX, <memory address>
Demo:
Here is an assembly program for us to dissect into.
global _start
section .text
_start:
; mov immediate data to register
mov rax, 0xaaaaaaaabbbbbbbb
mov eax, 0xaaaaaaaa
mov rax, 0xaaaaaaaabbbbbbbb
mov al, 0x11
mov rax, 0xaaaaaaaabbbbbbbb
mov ah, 0xcc
mov rax, 0xaaaaaaaabbbbbbbb
mov ax, 0xdddd
; mov register to register
mov rbp, rax
mov r10, rbp
mov r11d, r10d
mov r12w, r11w
mov r13b, r12b
; mov from memory into register
mov rsi, [sample2]
mov r14d, [sample]
mov r15w, [sample]
mov dil, [sample]
; mov from register into memory
mov rax, [sample2]
mov byte [sample], al
mov word [sample], ax
mov dword [sample], eax
mov qword [sample], rax
; lea demo
lea rax, [sample]
lea rbx, [rax]
; xchg demo
mov rax, 0x1234567890abcdef
mov rbx, 0x9999999999999999
xchg rax, rbx
; exit the program gracefully
mov rax, 0x3c
mov rdi, 0
syscall
section .data
sample: db 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22
sample2: dq 0x1122334455667788
sample3: times 8 db 0x00
Note at the end we are exiting by giving rax a value 0x3c which is hex equivalent of "60" which is the syscall number of exit()
gdb -q ./MovingData -tui
Instruction 1: Rule A applies

Instruction 2: Note how a 32 bit value output zeros out the upper 32 bits of the register. 3rd instruction resets RAX.

Instruction 4: Rule C applies and the remaining 30 bits are unaffected

Instruction 9: Moves rax into rbp

Instruction 14: This instruction assigns value of sample2 variable in RSI.

On stepi we'll see the change

Instruction 19: Changes sample variables 1 byte with that of al.

Notice al has 88 right now and sample starts with 0xaa. This gets overwritten

Instruction 23: LEA would load 0x402000 intro RAX. Note that this is the memory address of sample variable.

Upon stepi or si, we see RAX being overwritten with the address of sample

Instruction 24: This instruction (lea rbx, [rax]) essentially loads the value in RAX into RBX

Instruction 27: This instruction would exchange RAX and RBX. Notice how rax and rbx have been overwritten first by 64 bit absolute values

One more stepi

Finally, we exit the program using 0x3c (hex value for 60->syscall number for exit()) with rdi as 0 for error code.

Last updated
Was this helpful?