Basic Assembly Tutorial, part 4

February 2016, Cremona, Italy

Back to Homepage
Back to ASM index


Lesson 4

Conditional instructions

Let's introduce the instructions jmp and cmp, that are used respectively to jump to a label and to compare two values.

JMP

The jmp instruction make execution of code proceed to the point where you put a certain label. Putting a label is straightforward: you just choose a name followed by a comma.

Here's a simple example: when the program execution meets the jmp instruction, jumps to label2, ignoring the part of code between, and proceeds from there on.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .data msg1 db 'I have jumped to label 1.', 0xA len1 equ $ - msg1 msg2 db 'I have jumped to label 2.', 0xA len2 equ $ - msg2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .text global _start _start: ; start fetching the registers for calling sys_write mov eax, 4 ; sys_write mov ebx, 1 ; stdout jmp label2 label1: ; put 'msg1' into registers mov ecx, msg1 ; message memory address mov edx, len1 ; message length int 0x80 label2: ; punt 'msg2' into registers mov ecx, msg2 mov edx, len2 int 0x80 ;;;;; Now exit ;;;;; mov eax, 1 mov ebx, 0 int 0x80
Once again, the '0xA' after messages just append the ASCII code for 'new line' to the string.

CMP

The CMP instruction compares two values and sets a flag. You can then execute conditional jumps based on the result of CMP, with instructions JE (jump if equal), JNE (jump if not equal) etc.
Example: not equal values
[code here] cmp ah, bh ; compares ah with bh and stores result in internal flag jne exit ; if not equal, jump to label 'exit' [some more code that is executed only if values in ah and bh are equal] exit: ; code jumps directly here if codes are not equal mov eax, 1 mov ebx, 0 int 0x80
Since in assembly there are no such notions as integers, characters and stuff, but only bytes the comparation process should introduce no doubt.

Here's a table of a few conditional instructions.
Instruction Meaning
je == , equal
jne != , not equal
jg > , greater
jge >= , greater or equal
jl < , lesser
... ...

Example: menu program

This simple example shows a menu and gives you some choices:
;;;;;; Macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro print_msg 2 mov eax, 4 ; sys_write mov ebx, 1 ; stdout mov ecx, %1 ; message address mov edx, %2 ; message length int 0x80 ; perform system call %endmacro %macro get_keys 2 mov eax, 3 ; sys_read mov ebx, 0 ; stdin mov ecx, %1 ; memory location to store data mov edx, %2 ; data length int 0x80 ; perform system call %endmacro %macro exit 1 mov eax, 1 ; sys_exit mov ebx, %1 ; error status int 0x80 ; perform system call %endmacro ;;;;;; Data Section ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .data ; Buffer Size BUFSIZE equ 512 ; menu message menumsg db '-----------------------',0xA, \ ' 1 -> input message', 0xA, \ ' 2 -> print message', 0xA, \ ' 0 -> exit', 0xA, \ '-----------------------',0xA,0xA menulen equ $ - menumsg writemsg db ' Write your message here: ' writelen equ $ - writemsg yourmsg db ' Your message is: ' yourlen equ $ - yourmsg emptylines db 0xA, 0xA ; two empty lines emptylen equ $ - emptylines ;;;;;; Bss Section ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .bss choice resb 2 ; 2 bytes: the first is character, ; second is ascii for ENTER inputmsg resb BUFSIZE ; BUFSIZE defined in data sect. ;;;;;; Text Section ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section .text global _start ; defined for linker _start: ; Print menu print_msg menumsg, menulen ; read choice get_keys choice, 2 ; get 2 bytes: the first is character ; and second is ascii for ENTER ; ------- Compare choices ------------ mov ah, [choice] ; Did you press 0? cmp ah, '0' je choice0 ; Did you press 1? cmp ah, '1' je choice1 ; Did you press 2? cmp ah, '2' je choice2 ; -------- Here are various parts ------- choice0: ; If you choosed '0', program jumps you here exit 0 choice1: ; If you choosed '1' program jumps you right here ; this part prints 'Hei, input message!' and then saves it ; at location 'inputmasg'. Maximum size is BUFSIZE. print_msg writemsg, writelen get_keys inputmsg, BUFSIZE print_msg emptylines, emptylen ; one empty line.. jmp _start choice2: ; This part shows the message stored at 'inputmsg'. ; If you havn't stored yet it will be empty or random.. print_msg yourmsg, yourlen print_msg inputmsg, BUFSIZE print_msg emptylines, emptylen jmp _start


A sample output is like this: ----------------------- 1 -> input message 2 -> print message 0 -> exit ----------------------- 2 Your message is: Heila', fratello!

Including files

You can tell the NASM assembler to include files using the %include directive. For example, you could create a file of macros and then include them, without needing to writing them every single time!
Syntax:
%include "macrosfile.mac"
The file can be in the same directory or in another directory specified to NASM by the option -i. Another way of including files is doing it by bruteforce with the option -p.