Peter Mawhorter
*Some formats support arbitrary segments
.
(reference)$
(or lea
) to use address as a
value:$
(or lea
) to use address as a
value:0000000000401136 <msg>:
401136: 48 rex.W
401137: 69 .byte 0x69
401138: 7e 0a jle 401144 <show+0x9>
40113a: 00 .byte 0x0
000000000040113b <show>:
40113b: 48 c7 c7 36 11 40 00 mov $0x401136,%rdi
401142: 48 c7 c0 00 00 00 00 mov $0x0,%rax
401149: e8 e2 fe ff ff call 401030 <printf@plt>
40114e: c3 ret
.data
segment?.text
segment?printf
?disas
and x
commands
disas
will show the current functionstepi
will step one instructionbreak
to set breakpoints*
for
address-based; like break *show+7
)info reg rsp
(or another register) show contents$rsp
(or another register) w/ x
:x /4xg $rsp
would show first 4 quads on stackx /s $rdi
to show string pointed to by
%rdi
.data
# global variable z
z: .long 0
# format string for printf (read-only)
fmt: .string "Calculation produces %d\n"
.text
# Multiplies arg1 with itself and returns result (32-bit)
.global square
square:
# multiply %edi by iteslf
# copy %edi to %eax
# return
.global main
main:
# Don't forget to align the stack and
# save callee-saved registers
# First call: square(3)
# Put 3 in %rdi, then call
# store result in a caller-saved register
# push that register before this call
# Second call: square(4)
# Put 4 in %rdi, then call
# pop the value we pushed
# store result in a caller-saved register
# (or directly add it to the other result)
# Add results into z
mov %?, z
# Setup args for printf
# Set %rax to 0
# Call printf
# Don't forget to undo any stack alignment
# Return 0
i
is at base + i * size
base
is the array address: the pointersize
is the size of each elementx[1]
is the same as *(x + 1)x[1][2]
is NOT ALWAYS the same
as *(*(x + 1) + 2)x[1][2]
only makes sense if we
know how big a row isx[1][1]
is x + 4*2 + 4 = x + 12
4×4 + 8 = 24 bytes used
Would an array wear pants…
…like this?
…or like this?
C uses row-major order: values are stored in-memory the same way that an English speaker would read them out: left-to-right across one row and then down to the next row.
In assembly, you can just write things out in order, or use multiple rows to make it more legible:
The nums
label just refers to the address of the first
element; compiler needs to be told what the data means.
extern int nums[3][3];