Human |
C++ |
Assembly |
Declare a long integer. |
long y; |
rdx (nothing to declare, just use a register) |
Copy one long integer to another. |
y=x; |
mov rdx,rax |
Declare a pointer to an long. |
long *p; |
rax (nothing to declare, use any 64-bit register) |
Dereference (look up) the long. |
y=*p; |
mov rdx,[rax] |
Find the address of a long. |
p=&y; |
mov rax,place_you_stored_Y |
Access an array (easy way) |
y=p[2]; |
(sorry, no easy way exists!) |
Access an array (hard way) |
p=p+2; y=*p; |
add rax,2*8; (move forward by two 8 byte longs) mov rdx,[rax] ; (grab that long) |
Access an array (too clever) |
y=*(p+2) |
mov rdx,[rax+2*8]; (yes, that actually works!) |
mov rcx,my_code ; rcx == address of the codeThis returns 5, because the "add eax" opcode is 0x05. Clearly, this is not an easy way to make arbitrary constants! Luckily, there's a "pseudo instruction" named "dq" (data QWORD) that inserts an 8-byte constant into the code at that point:
mov rax,[rcx] ; load the bytes of machine code
ret
my_code:
add eax,0 ; this *happens* to be opcode 5, in machine code
mov rcx,my_code ; rcx == address of the codeNote that the disassembly shows this as "add al", but we're just using it as a value!
mov rax,[rcx] ; load the bytes of machine code
ret
my_code:
dq 4 ; this inserts a literal value, stored as an 8-byte 64-bit "long".
mov rcx,my_arr ; rcx == address of the arrayKeep in mind that each element here is a "dq" or an 8-byte long, so I move down by 8 bytes during indexing, and I load into the 64-bit "rax".
mov rax,[rcx+1*8] ; load element 1 of array
ret
my_arr:
dq 4 ; array element 0, stored at [my_arr]
dq 7 ; array element 1, stored at [my_arr+8]
dq 9 ; array element 2, stored at [my_arr+16]
mov rcx,my_arr ; rcx == address of the arrayHere's how you declare, store, and address values of all the sizes. The register names are just examples so you get the sizes right; you can load or store from any register.
mov eax,[rcx+1*4] ; load element 1 of array
ret
my_arr:
dd 0xaaabbbcc ; array element 0, stored at [my_arr]
dd 0xc001007 ; array element 1, stored at [my_arr+4]
Bits |
C++ |
Assembly Create |
Assembly Read |
Example |
8 |
char |
db (data byte) |
mov al, BYTE[rcx+i*1] |
(Try this in NetRun now!) |
16 |
short |
dw (data WORD) |
mov ax, WORD [rcx+i*2] | (Try this in NetRun now!) |
32 |
int |
dd (data DWORD) |
mov eax, DWORD [rcx+i*4] | (Try this in NetRun now!) |
64 |
long |
dq (data QWORD) |
mov rax, QWORD [rcx+i*8] | (Try this in NetRun now!) |
mov rcx,my_arr ; rcx == address of the arrayYou can reduce the likelihood of this type of error by adding explicit memory size specifier, like "WORD" below. That makes this a compile error ("error: mismatch in operand sizes") instead of returning the wrong value at runtime.
mov eax,[rcx] ; load element 0 of array (OOPS! 32-bit load!)
ret
my_arr:
dw 0xaabb ; array element 0, stored at [my_arr]
dw 0xbeef ; array element 1, stored at [my_arr+2]
mov rcx,my_arr ; rcx == address of the arrayIf we really wanted to load a 16-bit value into a 32-bit register, we could use "movzx" (unsigned) or "movsx" (signed) instead of a plain "mov".
mov eax, WORD [rcx] ; load element 0 of array (OOPS! 32-bit load!)
ret
my_arr:
dw 0xaabb ; array element 0, stored at [my_arr]
dw 0xbeef ; array element 1, stored at [my_arr+2]