Step 1 of 5 · Reading · ~4 min
Learn
Control Flow and Memory
Memory and Strings
By the end of this lesson you can read and write individual bytes anywhere in memory, step through an array by index, and build a new string from an old one. This is where assembly stops looking like calculator buttons and starts looking like programs.
Memory is numbered bytes
Memory is one long row of bytes, each with a number called its address. A label such as greeting is just a name for an address that the assembler works out. The square brackets are the dereference: they mean "the bytes at this address".
section .data
greeting db "memory", 0 ; 7 bytes: six letters and a zero
mov rsi, greeting ; rsi = the ADDRESS of the first letter
mov rax, [greeting] ; rax = the first 8 bytes of CONTENT, read as one number
mov al, [greeting + 3] ; al = 'o', the byte at index 3
The first two lines show the classic bug: mov rsi, label and mov rsi, [label] differ by one pair of brackets and mean address versus contents. lea rsi, [greeting] ("load effective address") computes the address without reading memory, so it equals the first form; it earns its keep with complicated bracket expressions.
Addressing modes
Inside the brackets the CPU can add up to four things in one instruction: [base + index*scale + displacement]. The base and index are registers, the scale must be 1, 2, 4 or 8, and the displacement is a constant.
| Form | Meaning |
|---|---|
[rbx] | the address held in rbx |
[rbx + 8] | 8 bytes past it |
[buf + rcx] | a label plus an index, for byte arrays |
[buf + rcx*4] | index times the element size, for arrays of 4-byte items |
[buf + rcx - 1] | the byte just before index rcx |
The width of the access comes from the register, or from a keyword: byte is 1 byte, word 2, dword 4, qword 8. cmp byte [rbx + 1], 0 compares exactly one byte; without byte, NASM would not know how wide the memory side is.
Sizes and byte order
x86 is little-endian: the least significant byte is stored at the lowest address.
section .data
num dd 0x11223344 ; dd = one 4-byte value
mov al, [num] ; al = 0x44, the first byte in memory
mov al, [num + 3] ; al = 0x11
So memory holds 44 33 22 11, which looks backwards only if you expect the number to be written left to right.
Walking an array
Summing an array of six 4-byte values, with the index scaled by the element size:
section .data
scores dd 4, 8, 15, 16, 23, 42
section .text
xor eax, eax ; total
xor ebx, ebx ; index
.next:
cmp rbx, 6
jge .end
add eax, [scores + rbx*4]
inc rbx
jmp .next
.end: ; eax = 108
Strings in memory work the same way with a scale of 1. A C-style string has no stored length, only a zero byte at the end. Counting to that zero gives the length:
xor ebx, ebx
.scan:
cmp byte [greeting + rbx], 0
je .found
inc rbx
jmp .scan
.found: ; rbx = 6
read does not add a zero. It returns a count in rax, and that count is the length you should use.
Where bytes live
.textis code..datais initialized data; its bytes are stored in the executable..bssis reserved space (resb 128is 128 bytes,resq 10is ten 8-byte values). It occupies no space in the file and starts as zeros. A buffer you fill at run time belongs here.
x86 also has string instructions such as rep movsb, which copies rcx bytes from [rsi] to [rdi] in one instruction. They are worth knowing, but a plain loop with an index does the same job and is easier to debug while you are learning.
Common mistakes
- Address versus contents.
mov rsi, [buf]loads text as if it were a pointer. - Off by one at the ends. The last element of an array of
nitems is at indexn - 1, notn. - Treating the newline as data. The count from
readincludes the0Aat the end of the line. - Writing the whole buffer. A 128-byte
.bssbuffer holds your text plus zeros; writing its full size prints the zeros too.
Your exercise
The starter reads a line into line and leaves the byte count in rax. Build the result in the rev buffer, not in place, and decide what exactly goes out to the terminal and how many bytes of it there are.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…