NASM

3. NASM

3.1 NASM

NASM is an assembler that we will use. To make things easier, we will use the NASM-X project. It is a collection of macros, includes, and examples to help NASM programmers develop applications.

How to install:

  1. Download NASMX and extract it to C:\nasmx

  2. Add the bin to environment variables

  3. Run setpath.bat

To work with demos:

  1. Comment the following line in C:\nasmx\demos\windemos.inc

%include 'nasm.inc'
  1. Add directly below it the following code

%include 'C:\nasmx\inc\nasmx.inc'
  1. Open C:\nasmx\demos\win32\DEMO1

  2. To use the assembler, we run the following command:

nasm -f win32 demo1.asm -o demo1.obj
  1. To link the object files, use golink, which is located in the same package (NASMX) when NASM is downloaded:

golink /entry _main demo1.obj kernel32.dll user332.dll
  1. A prompt will show up if the operations are successful

3.2 ASM Basics

High-level functions such as strcpy() are made of multiple ASM instructions put together to perform the given operation (copy of 2 strings)

The simplest assembly instruction is MOV that moves data from one location to another in memory.

Most instructions have 2 operands and fall into one of the following classes:

The following is an example of a simple assembly code that sums 2 numbers:

MOV EAX,2   ; store 2 in EAX
MOV EBX,5   ; store 5 in EBX
ADD EAX,EBX ; do EAX = EAX + EBX  operations
            : now EAX contains the result

3.2.1 Intel vs AT&T

Depending on the architectural syntax, instructions and rules may vary. For example, the source and the destination operands may be in different position.

example:

In AT&T syntax, % is put before registers names and $ is put before numbers. Another thing to notice is that AT&T adds a suffix to t he instruction, which defines the operand size:

  • Q (quad - 64 bits)

  • L (long - 32 bits)

  • W (word - 16 bits)

  • B (byte - 8 bits)

3.2.2 PUSH Instruction

As it has been said before, PUSH stores a value to the top of the stack, causing the stack to be adjusted by -4 bytes (on 32 bit systems): -0x04

Operation : PUSH 0x12345678

| | Before PUSH | After PUSH | | |-|-------------|------------| | |Lower memory address|||| || | 12345678 |<- Top of the Stack| |Top of the Stack -> | 00000001 | 00000001 | | | | 00000001 | 00000001 | | | | 00000001 | 00000001 | | | | 00000001 | 00000001 | | |Higher memory address|||||

Another interesting fact: PUSH 0x123456789 can be analogous to some other operations, for example:

SUB ESP, 4            ; subtract 4 to ESP -> ESP=ESP-4
MOV [ESP], 0X12345678 ; store the value 0x12345678 to the location
                      ; pointed by ESP. Square brackets indicates to
                      ; address pointed by the registers

3.2.3 POP Instruction

As it has been said before, POP stores a value to the top of the stack, causing the stack to be adjusted by +4 bytes (on 32 bit systems): +0x04

Operation : POP reg

| | Before PUSH | After PUSH | | |-|-------------|------------| | |Lower memory address|||| |Top of the Stack -> | 12345678 | || || 00000001 | 00000001 | <- Top of the Stack | | | 00000001 | 00000001 | | | | 00000001 | 00000001 | | | | 00000001 | 00000001 | | |Higher memory address|||||

Another interesting fact: POP EAX can be analogous to some other operations, for example:

MOV EAX, [ESP]        ; store the value pointed by ESP to EAX
                      ; the value at the top of the stack
ADD ESP, 4            ; add 4 to ESP - adjust the top of the stack

3.2.4 CALL Instruction

Subroutines are implemented by using CALL and RET instruction pair.

The CALL instruction pushes the current instruction pointer (EIP) to the stack and jumps to the function address specified.

Whenever the function executes the RET instruction, the last element is popped from the stack, and the CPU jumps to the address.

Example of CALL in Assembly:

MOV EAX, 1      ; store 1 in EAX
MOV EBX, 2      ; store 2 in EBX
CALL ADD_sub    ; call the subroutine named 'ADD_SUB'
INC EAX         ; Increment EAX: now EAX holds "4"
                ; 2(EBX)+1(EAX)+1(INC)
JMP end_sample
ADD_sub:
ADD EAX, EBX
RETN            ; Function completed
                ; so return back to caller function
end_sample:

The following is an example of how to call a procedure. This example begins at proc_2:

proc proc_1
     Locals none
     MOV ECX, [EBP+8] ; ebp+8 is the function argument
     PUSH ECX
     POP ECX
end_proc
proc proc_2
     Locals none
     invoke proc_1, 5 ; invoke proc_1 proc
endproc

3.2.5. LEAVE Instruction

Is the same with

mov esp, ebp
pop ebp

You can learn more about assembly online by yourself.

Last updated