I have dug in simple binaries, such as though like x86 bootloaders, Sega video game binaries, etc. I know that these files tend to use assembler macros to define data, etc. What I am having trouble figuring out is what assemblers tend to translate macros into exactly (are they instructions, custom formatted data entries used statically, addressing mode/special opcodes, etc.).

Example, x86 assemblers support DEFINE BYTE macros. What is the assembling process of these (and similar) macros an assembler will turn to binary? Do they become static, custom binary format used within file itself, do they become x86 instruction, etc.?

Example you could try:

[ORG 0x7C02]
[BITS 16]
jmp $
times 510-($-$$) db 0
dw 0xAA55
  • 1
    You cannot say "what" the data bytes will be used for. db values are written into the executable file, and only when executing this file you can determine how they are used -- i.e., read, written to, or even executed. The db command itself assumes nothing; and neither does an assembler.
    – Jongware
    Feb 9 '14 at 17:07

An assembly language is much more than a set of mnemonics that translate to machine code. The syntax of an assembly language will dictate how you specify operands, the order in which they are specified, how to specify the size of the operands and much more.

In addition an assembly language will generally include a set of directives to help make your life easier and may include a facility for declaring macros. There is a distinction between directives such as dd, resd, and times which instruct the assembler to do very specific things and macros which are generally just shortcuts which are expanded by the assembler during a preprocessing phase. Macros may expand to code, data, directives or any combination thereof.

In the case of your example, the assembler is being asked to pad with zeros (db 0) out to a size of 510 bytes (510 - ($-$$)), finally the word value 0xAA55 will be appended to make the total section size 512 bytes.

More generally, data declarations such as db, dw,and dd get translated into initialized data in a .data section, while data "reservations" such as resb may be translated into file sections that results in the creation of a .bss section which gets allocated at process load time. Please keep in mind that much of this is also dependent on any section directives that you may use which also dictate when and where data may be allocated.

  • You say "data section" ... no such thing to the CPU. You mean it gets stored somewhere....
    – School Pup
    Feb 8 '14 at 18:12
  • @SchoolPup: so? Your jmp $ statement also gets stored somewhere - by default in a 'code section'. 'Data' means nothing to a CPU either; it gets handed an address and is instructed to read from it. It does not care where that address points to or whether what it reads is 'data' or 'code', or even an external data port.
    – Jongware
    Feb 9 '14 at 17:11
  • 1
    The original question is "What exactly do assemblers translate macros into?" How the CPU views anything is irrelevant to the discussion. Assemblers translate statements into machine code or data that is for the most part into sections (.text, .data, etc) in a file that adheres to some standard format such as ELF, PE, etc. Feb 10 '14 at 5:02

db 0xxh will be encoded as it is in binary so if db 0cch was issued

just one byte 0xcc will be encoded in the exact position db was issued

dw will encode one word

ie dw 0aa55h will be seen as AA 55 in the binary

dd = DWORD == 2 WORDS == 4 BYTES so dd 01337BABEh will be encoded as 13 37 ba be in binary
dq = qword == 2 dwords == 4 words == 8 bytes

contents of directory prior to assembling and linking

   :\>dir /b

contents of asm file

:\>type bootlo.asm
.model flat, stdcall
ORG 337h
jmp @F
db 0bh dup (0CCh)
dw 0AA55h
dd 01337babeh
dq 05D0DDEED1337BABEh
end start

assembling the file

:\>ml /coff /nologo  bootlo.asm /link /subsystem:windows /nologo  

 Assembling: bootlo.asm

contents of directory post assembly and link

:\>dir /b

explanation follows

org 337 has become default start of code section + 337  

ie 0x1000 + 0x337  so during runtime it would be entry point RVA + default base 

ie  0x400000 + 0x1000 + 0x337 == 0x401337   

at 401337 you have will have a jump encoded whose size would be the differnce between the address of next label and current instruction

next label follows after

db 0bh i encoded 0xcc in example but 0xab or 0xff or 0x00 or any byte can be encoded and assembler will emit exactly what was asked for & how many times it was asked for

so there will be a short jump viz eb 0b (x86 opcode )

follwing the label dw 0AA55h is issued so at 400000 + 1000 + 337 + 0x0b
AA 55 or 55 AA should be seen at 401344 (beware endianness)

assembled binary can be dumped and checked if AA 55 exists

:\>echo. & dumpbin /ALL bootlo.exe | grep -i entry & echo. & dumpbin /all bootlo
.exe | grep -A 1 -B 1 -i 55

1337 RVA of entry point

  00401330: 00 00 00 00 00 00 00 EB 0B CC CC CC CC CC CC CC  .......δ.╠╠╠╠╠╠╠
  00401340: CC CC CC CC 55 AA BE BA 37 13 BE BA 37 13 ED DE  ╠╠╠╠U¬╛║7.╛║7.φ▐
  00401350: 0D 5D C3                                         .]├


What you are referring to are additional information or macros that are inserted at the assembler level by the compiler before going to the linker.

In fact, the linker may use these information to optimize the final executable file (in term of size or memory layout of the different procedures). And, macros may be replaced by template functions that lies inside your compiler.

But, all these information and macros are only present here because what you see is an on-going work. The compiler need still to swallow a bit more the assembler file before outputting a real executable file. And, at the very end of the process, all these intermediate flags (destined to the compiler) will be removed and/or replaced by actual code.

Here is a small example.

C file

#include <stdio.h>

int main ()
  printf("Hello World!\n");
  return 0;

Assembler file (before linker)

    .file   "sample.c"
    .section    .rodata
    .string "Hello World!"
    .globl  main
    .type   main, @function
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $.LC0, %edi
    call    puts
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    .size   main, .-main
    .ident  "GCC: (Debian 4.8.2-14) 4.8.2"
    .section    .note.GNU-stack,"",@progbits

Pure executable file (after linker)

00000000004004fd <main>:
  4004fd:       55                      push   %rbp
  4004fe:       48 89 e5                mov    %rsp,%rbp
  400501:       bf c4 05 40 00          mov    $0x4005c4,%edi
  400506:       e8 d5 fe ff ff          callq  4003e0 <puts@plt>
  40050b:       b8 00 00 00 00          mov    $0x0,%eax
  400510:       5d                      pop    %rbp
  400511:       c3                      retq   
  400512:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  400519:       00 00 00 
  40051c:       0f 1f 40 00             nopl   0x0(%rax)
  • I don't think that answers my question ... for example, you are using a compiler, not an assembler, and you used no macros anyways. Sorry, but this answer doesn't help, nor does it exactly address what I asked specifically. You are also talking about higher-level code ... I was asking about lower-level code, such as a straight-assembled x86 bootloader with macros for byte declarations and possibly origin. That's what I want to know about ... how does that stuff end up in the binary, and how so does it play its part afterwards?
    – School Pup
    Feb 6 '14 at 17:09
  • But, I don't think that these "macro" end-up in the binaries. They are either left by the compiler before the transformation to binaries, or rebuilt by the disassembler from a static analysis of the program. What I tried to explain was that there are several levels in "assemblers" which can be commented or tagged with information useful for the compiler or other targets). A question that comes to my mind is: Where does come from the assembly that you are considering ? From a compiler or from a disassembler ?
    – perror
    Feb 6 '14 at 17:48
  • Assembler ... Assembler ... I specified assembly code. Macros and directive s are similar it seems, but I wanted to know how the assembler structures and writes the data to the "file", and how the code may use static data, as opposed to data just pulled from RAM in a machine instruction
    – School Pup
    Feb 8 '14 at 18:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.