CSC231 2-Hour Crash Course
This lab assumes that you have the open-source nasm assembler available and that you are working under Linux or Mac OS X. The one-evening assembly crash course is meant to present assembly language concepts on the Pentium as a preparation for writing assembly language programs in Hexadecimal for the 6801 HeathKit.
Note: Information about how to make nasm, ld, and gcc work together is provided in the Sys-Admin section at the end...
Contents
The architecture of the Pentium
- Registers
- EAX, EBX, ECX, EDX
- ESI, EDI
- EIP
- ESP, EBP
Login
- Login to Hadoop0
Simple I/O in assembly
Get a copy of the following programs. If you are using 270b-xx class accounts, try using the getcopy command to copy them directly into your working directory.
Example of how you would get the files to your 270b-xx account:
getcopy driver.c getcopy asm_io.asm getcopy asm_io.inc getcopy prog1.asm
Exercise #1:
Assemble, link and run the program.
nasm -f elf asm_io.asm # (do this only once for all the exercises) nasm -f elf prog1.asm gcc -o prog1 -m32 driver.c prog1.o asm_io.o ./prog1
Basic instructions and operands
- mov dest, src
- add dest, src
- prog2.asm
section .data
a dd 3
b dd 5
result dd 0
section .text
global asm_main
asm_main:
mov eax,[a]
add eax,[b]
mov [result],eax
mov eax,[result] ; pass result to print_int
call print_int ; and print value
ret
Exercise #2
Create and run the program. Verify that it outputs the sum of the two variables
Exercise #3
Modify the program so that it computes the sum of 5 variables containing the numbers 3, 5, 8, 10, and 20. Your program should output this sum.
Addressing Modes
we can access memory using the address of a variable plus an offset:
a dd 3
b dd 5
...
; sum up two variables in eax
mov eax, [a]
add eax, [b]
; can also be written as
mov eax, [a]
add eax, [a+4]
When dealing with an array of several values, it's easier to use an index, either ESI, or EDI.
table dd 3, 5, 8, 10, 20
result dd 0
mov esi,table ; esi gets address of table variable
mov eax,[esi] ; get first dword of table in eax
add esi, 4 ; make esi point to next dword
add eax, [esi] ; add second dword of table to eax
add esi, 4 ; make esi point to third dword
add eax, [esi] ; add third dword to eax
add esi, 4 ; esi points to 4th dword
add eax, [esi] ; add 4th dword to eax
add esi, 4 ; esi points to last dword
add eax, [esi] ; add last dword to sum
mov [result],eax ; save sum in variable result
If needed, we can use and offset along with the index. Here's another way of summing up two variables:
a dd 3
b dd 5
result dd 0
...
mov esi, a ; make esi point to a
mov eax, [esi] ; get 1st variable
add eax, [esi+?] ; figure out what number to use!
mov [esi+?],eax ; store result. Figure out the offset!
Exercise #4
Write the program that will store the first five fibonacci numbers in the array table defined as:
table dd 1, 1, 0, 0, 0
The final content of the table should be 1, 1, 2, 3, 5. Your program should use the recurrence equation:
Fibn = Fibn-1 + Fibn-2.
Loops
Loops can easily be implemented: store the number of times you need to repeat a block of code in ecx, and prefix the first instruction of the block with a label, as follows:
mov ecx, 5 ; get ready to loop 5 times
mov eax, 1 ; start with 1 in eax
repeat: call print_int ; print eax to the screen
add eax, 2 ; add 2 to eax
loop repeat ; repeat 5 times
Exercise #5
Rewrite the program that sums up the 5 numbers in the array table using a loop.
Tests
Tests can be used to compare quantities and to perform a two-way branch depending on the result.
cmp eax, 3 ; compare eax to 3 jne there ; if they are not equal, go to "there" mov eax, msg1 ; otherwise print msg1 call print_string jmp done ; skip over next 2 instructions there: mov eax, msg2 ; print msg2 call print_string
done: ... ; end up here in both cases
If eax contains a value different from 3, the code above prints whatever string is at address msg2, otherwise, if eax is 3, the code prints the contents of msg1.
Exercise #6
Assume that you have an array of 10 numbers, write the code that will print only the numbers that are different from 0.
table dd 0, 1, 0, 10, 11, 4, 0, 0, 100, 0
Functions
Functions work in a way similar to the functions used in higher level language, except that there isn't a natural way to pass parameters. Parameters are typically passed in registers (by preloading the eax, ebx, ecx, or edx registers before the call), or by pushing them in the stack before calling the function. For today, we'll look only at passing parameters via registers. Let's write a program that uses a function to which we pass two integers, say 3, and 5, and the function outputs:
the sum of 3 and 5 is 8
If we pass it two new values, say 10, and 20, it will output
the sum of 10 and 20 is 30
section .text
global asm_main
;;; -----------------------------------------------------------
;;; sumfunc: ebx and ecx are assumed to contain 2 integers that
;;; this function will add together, and display
;;; a string of the form "the sum of x and y is z"
;;; msg1, msg2, and msg3 are 3 strings declared in the
;;; data segments
;;; -----------------------------------------------------------
sumfunc: mov eax, msg1 ; "the sum of "
call print_string
mov eax, ebx ; print int in ebx
call print_int
mov eax, msg2 ; " and "
call print_string
mov eax, ecx ; print int in ecx
call print_int
mov eax, msg3 ; " is "
call print_string
... ; figure out what 3 instructions
... ; are necessary to print ebx plus
... ; ecx
call print_nl ; print new-line character
ret
asm_main:
mov ebx, 3
mov ecx, 5
call sumfunc ; prints "the sum of 3 and 5 is 8"
mov ebx, 10
mov ecx, 20
call sumfunc ; prints "the sum of 10 and 20 is 30"
Exercise #7
Assume that we have two arrays of integers, A, and B. A has 5 integers. B has 10 integers. Write a function to which we can pass an array and the number of integers it contains, and the function displays only the numbers of the array that are not zero.
A dd 1, 0, 2, 0, 5
B dd 1, 0, 0, 3, 1, 2, 0, 0, 9, 7
Solutions
prog1.asm prog2.asm prog3.asm prog4.asm prog5.asm prog6.asm prog7.asm
Information for the Sys-Admin
- To make nasm, ld, and gcc work together, we have to stay in 32-bit mode, even though the architecture is 64 bit long.
- nasm should be a recent version
- gcc will be in 64-bit mode, and libgcc-devel.i386 should be installed to allow gcc to compile and link 32-bit object files
On Ubuntu
- Login to Hadoop0
- install libgcc-devel
sudo apt-get install libc6-dev-i386
- test sample program (prog1.asm) above:
nasm -f elf prog1.asm nasm -f elf asm_io.asm gcc -m32 driver.c *.o ./a.out
- It should work!
On Fedora
- Haven't solved that yet...