Assemblers Are Just Different Dialects Of Assembly.

Assemblers Are Just Different Dialects Of Assembly.

September 28, 2025


Assemblers are just different dialects of the same assembly language. In the end, the object code remains the same for a nasm source and gas source doing the same thing the same way, just different directives.

This thing is so trivial that we don’t even require gdb to verify it.

Take these sources:

This uses nasm directives.

nasm.s
section .data
val dq 42            ; 42 as a 64-bit value

section .text
global _start

_start:
  mov rax, [val]      ; load value into rax
  mov rdi, rax        ; move it into rdi for exit code
  mov rax, 60         ; syscall: exit
  syscall

This uses gas directives.

gas.s
.data
val: .quad 42         # 42 as a 64-bit value

.text
.global _start

_start:
  movq val, %rax      # load value into rax
  movq %rax, %rdi     # move into rdi for exit code
  movq $60, %rax      # syscall: exit
  syscall

Assemble them.

nasm -f elf64 nasm.s -o nasm.o
as gas.s -o gas.o

Stop. What do we need to verify?

  • If assembler directives are just dialects, the object code should be the same.

Let’s use objdump to disassemble both the object codes.

objdump -D nasm.o > nasm.txt
objdump -D gas.o  > gas.txt

Open both the files and you will see this:

nasm.txt

nasm.o:     file format elf64-x86-64


Disassembly of section .data:

0000000000000000 <val>:
   0:	2a 00                	sub    (%rax),%al
   2:	00 00                	add    %al,(%rax)
   4:	00 00                	add    %al,(%rax)
	...

Disassembly of section .text:

0000000000000000 <_start>:
   0:	48 8b 04 25 00 00 00 	mov    0x0,%rax
   7:	00 
   8:	48 89 c7             	mov    %rax,%rdi
   b:	b8 3c 00 00 00       	mov    $0x3c,%eax
  10:	0f 05                	syscall
gas.txt

gas.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <_start>:
   0:	48 8b 04 25 00 00 00 	mov    0x0,%rax
   7:	00 
   8:	48 89 c7             	mov    %rax,%rdi
   b:	48 c7 c0 3c 00 00 00 	mov    $0x3c,%rax
  12:	0f 05                	syscall

Disassembly of section .data:

0000000000000000 <val>:
   0:	2a 00                	sub    (%rax),%al
   2:	00 00                	add    %al,(%rax)
   4:	00 00                	add    %al,(%rax)
	...

If you rearrange the content in one of the files, you get this:

nasm.txt

nasm.o:     file format elf64-x86-64


Disassembly of section .data:

0000000000000000 <val>:
   0:	2a 00                	sub    (%rax),%al
   2:	00 00                	add    %al,(%rax)
   4:	00 00                	add    %al,(%rax)
	...

Disassembly of section .text:

0000000000000000 <_start>:
   0:	48 8b 04 25 00 00 00 	mov    0x0,%rax
   7:	00 
   8:	48 89 c7             	mov    %rax,%rdi
   b:	b8 3c 00 00 00       	mov    $0x3c,%eax
  10:	0f 05                	syscall
gas.txt

gas.o:     file format elf64-x86-64


Disassembly of section .data:

0000000000000000 <val>:
   0:	2a 00                	sub    (%rax),%al
   2:	00 00                	add    %al,(%rax)
   4:	00 00                	add    %al,(%rax)
	...

Disassembly of section .text:

0000000000000000 <_start>:
   0:	48 8b 04 25 00 00 00 	mov    0x0,%rax
   7:	00 
   8:	48 89 c7             	mov    %rax,%rdi
   b:	48 c7 c0 3c 00 00 00 	mov    $0x3c,%rax
  12:	0f 05                	syscall

Run diff on them.

diff gas nasm
  • Only the 19th line is different because GAS used rax and NASM used eax, which is a small assembler optimization.
  • Line 20 is also the same except that 10/12 thing.

Conclusion

This proves that our choice to learn x64 assembly, instead of getting drowned in assemblers was a right choice and assemblers are indeed just dialects of the same assembly language.

Last updated on