Difference between revisions of "CSC231 Exercises with conditinal jumps Solutions"
(→Loop until overflow) |
(→Print 2-dimensional arrays) |
||
(10 intermediate revisions by the same user not shown) | |||
Line 58: | Line 58: | ||
3 Solution programs: | 3 Solution programs: | ||
* [[CSC231 FibOverflowByte.asm | FibOverflowByte.asm]]: using an array of bytes | * [[CSC231 FibOverflowByte.asm | FibOverflowByte.asm]]: using an array of bytes | ||
− | * [[CSC231 | + | fib(2) = 2 |
− | * [[CSC231 | + | fib(3) = 3 |
+ | fib(4) = 5 | ||
+ | fib(5) = 8 | ||
+ | fib(6) = 13 | ||
+ | fib(7) = 21 | ||
+ | fib(8) = 34 | ||
+ | fib(9) = 55 | ||
+ | fib(10) = 89 | ||
+ | |||
+ | * [[CSC231 FibOverflowWorde.asm | FibOverflowWord.asm]]: using an array of words | ||
+ | |||
+ | fib(2) = 2 | ||
+ | fib(3) = 3 | ||
+ | fib(4) = 5 | ||
+ | fib(5) = 8 | ||
+ | fib(6) = 13 | ||
+ | ... | ||
+ | fib(19) = 6765 | ||
+ | fib(20) = 10946 | ||
+ | fib(21) = 17711 | ||
+ | fib(22) = 28657 | ||
+ | |||
+ | * [[CSC231 FibOverflowDWord.asm | FibOverflowDWord.asm]]: using an array of dwords | ||
+ | |||
+ | fib(2) = 2 | ||
+ | fib(3) = 3 | ||
+ | fib(4) = 5 | ||
+ | fib(5) = 8 | ||
+ | ... | ||
+ | fib(43) = 701408733 | ||
+ | fib(44) = 1134903170 | ||
+ | fib(45) = 1836311903 | ||
+ | |||
+ | All 3 programs require | ||
+ | * [[CSC231 driver.c | driver.c ]] | ||
+ | * [[CSC231 asm_io.inc | asm_io.inc]] | ||
+ | * [[CSC231 asm_io.asm | asm_io.asm]] | ||
==Scanning an array== | ==Scanning an array== | ||
− | Find the '''largest''' element of a 1-dimensional array of '''signed double-words'''. | + | * Find the '''largest''' element of a 1-dimensional array of '''signed double-words'''. |
+ | |||
+ | <code><pre> | ||
+ | section .data | ||
+ | msg1 db "large of array = ",0 | ||
+ | array dd 1, 3, 10, 0, -2, 44, 10 | ||
+ | N equ ($-array)/4 | ||
+ | |||
+ | |||
+ | ;; ------------------------- | ||
+ | ;; code area | ||
+ | ;; ------------------------- | ||
+ | section .text | ||
+ | global asm_main | ||
+ | |||
+ | ;;; --------------------------------------------------------- | ||
+ | ;;; main program | ||
+ | ;;; --------------------------------------------------------- | ||
+ | asm_main: | ||
+ | |||
+ | ;;; largest = MOSTNEG; | ||
+ | ;;; for ( i=0; i<N; i++ ) { | ||
+ | ;;; if ( array[i]>largest ) | ||
+ | ;;; largest = array[i]; | ||
+ | ;;; | ||
+ | ;;; print "largest of array = ", largest | ||
− | + | mov esi, 0 | |
+ | mov ebx, 0x80000000 ; most negative dword | ||
+ | |||
+ | for: cmp esi, N*4 | ||
+ | jge done | ||
+ | |||
+ | cmp ebx, dword[array+esi] | ||
+ | jg next | ||
+ | mov ebx, dword[array+esi] | ||
+ | next: add esi, 4 | ||
+ | jmp for | ||
+ | done: | ||
+ | mov eax, ebx | ||
+ | call printMax | ||
+ | |||
+ | ret | ||
+ | ;;; ---------------------------------------------------------- | ||
+ | ;;; printMax: gets integer in eax and prints it | ||
+ | ;;; ---------------------------------------------------------- | ||
+ | printMax: | ||
+ | push eax ; save max in stack | ||
+ | mov eax, msg1 | ||
+ | call print_string ; prints " " | ||
+ | pop eax ; get max from stack | ||
+ | call print_int ; print fact(i) | ||
+ | call print_nl ; next line | ||
+ | ret | ||
+ | </pre></code> | ||
+ | |||
+ | * Same question, but with '''unsigned double words'''. | ||
+ | |||
+ | ::For unsigned double words, then change the definition of the array (so that it does not contain negative numbers), and replace the '''jg next''' instruction by '''ja next''' instruction. | ||
==Characters and lower/upper case conversion== | ==Characters and lower/upper case conversion== | ||
Line 73: | Line 165: | ||
Modify the program so that it modifies only characters between 'a' and 'z' included. | Modify the program so that it modifies only characters between 'a' and 'z' included. | ||
+ | |||
+ | <code><pre> | ||
+ | ;;; makeUpper.asm | ||
+ | ;;; D. Thiebaut | ||
+ | ;;; | ||
+ | ;;; transforms a string to its uppercase equivalent | ||
+ | ;;; (works only if the string contains only letters) | ||
+ | ;;; | ||
+ | ;;; nasm -f elf xxxx.asm | ||
+ | ;;; gcc -o xxxx driver.c asm_io.o xxxx.o | ||
+ | ;;; | ||
+ | %include "asm_io.inc" | ||
+ | |||
+ | ;; ------------------------- | ||
+ | ;; data segment | ||
+ | ;; ------------------------- | ||
+ | section .data | ||
+ | str1 db "NabucoDonoSOR was king of Babylon!!!",0 | ||
+ | STR1LEN equ $-str1-1 | ||
+ | MASK equ 32 | ||
+ | |||
+ | section .bss | ||
+ | |||
+ | ;; ------------------------- | ||
+ | ;; code area | ||
+ | ;; ------------------------- | ||
+ | section .text | ||
+ | global asm_main | ||
+ | asm_main: | ||
+ | |||
+ | ;;;--- print the original string --- | ||
+ | mov eax,str1 | ||
+ | call print_string | ||
+ | call print_nl | ||
+ | |||
+ | ;;;--- force characters to uppercase --- | ||
+ | mov ebx,str1 | ||
+ | mov ecx,STR1LEN | ||
+ | mov ah, MASK | ||
+ | not ah | ||
+ | for: mov al, byte[ebx] | ||
+ | cmp al, 'a' | ||
+ | jb next | ||
+ | cmp al, 'z' | ||
+ | ja next | ||
+ | and byte[ebx], ah | ||
+ | next: | ||
+ | inc ebx | ||
+ | loop for | ||
+ | |||
+ | ;;;--- print new string --- | ||
+ | mov eax,str1 | ||
+ | call print_string | ||
+ | call print_nl | ||
+ | |||
+ | |||
+ | ;; return to C program | ||
+ | |||
+ | ret | ||
+ | |||
+ | </pre></code> | ||
==Long/short jumps== | ==Long/short jumps== | ||
Line 86: | Line 239: | ||
when the instruction at Label ''there'' is 1000 bytes away from the jl conditional jump? | when the instruction at Label ''there'' is 1000 bytes away from the jl conditional jump? | ||
+ | |||
+ | <code><pre> | ||
+ | |||
+ | cmp eax,10 | ||
+ | jge next | ||
+ | jmp there | ||
+ | next: | ||
+ | ... | ||
+ | ... | ||
+ | there: ... | ||
+ | |||
+ | |||
+ | </pre></code> | ||
==Print 2-dimensional arrays== | ==Print 2-dimensional arrays== | ||
Line 103: | Line 269: | ||
db "# #### #" | db "# #### #" | ||
db "################################" | db "################################" | ||
− | + | width equ maze2-maze ; num of columns | |
− | + | height equ 7 ; num of rows | |
i dd 0 | i dd 0 | ||
j dd 0 | j dd 0 | ||
+ | </pre></code> | ||
+ | |||
+ | |||
+ | A solution... | ||
+ | |||
+ | <code><pre> | ||
+ | ;;; ----------------------------------------------------------------------- | ||
+ | ;; printMaze: prints the maze in the maze variable | ||
+ | ;; Nothing needs to be passed | ||
+ | ;;; ----------------------------------------------------------------------- | ||
+ | printMaze: | ||
+ | initfori1: | ||
+ | mov dword[i],0 ;Start at 1st row | ||
+ | mov ecx,height ;Loop once for each row | ||
+ | fori1: push ecx ;Store loop counter | ||
+ | intiforj1: | ||
+ | mov dword[j],0 ;1st column | ||
+ | mov ecx,width ;Loop once for each column | ||
+ | forj1: | ||
+ | push ecx | ||
+ | ;; Get ready to call offset fn | ||
+ | mov eax, [i] | ||
+ | mov ebx, [j] | ||
+ | call ijoffset | ||
+ | mov al, byte[maze+eax] ;Get correct character in maze | ||
+ | call print_char | ||
+ | inc dword[j] ;go to next column | ||
+ | pop ecx ;Retrieve loop counter | ||
+ | loop forj1 | ||
+ | |||
+ | call print_nl | ||
+ | pop ecx | ||
+ | inc dword[i] ;next row | ||
+ | loop fori1 | ||
+ | ret | ||
+ | |||
+ | ;;; ----------------------------------------------------------------------- | ||
+ | ;; ijoffset: gets a coordinate in the maze, taking the row # from eax | ||
+ | ;; and the column # from ebx, and calculates the | ||
+ | ;; appropriate offset and stores it in eax. | ||
+ | ;; uses eax, ebx, ecx | ||
+ | ;;; ----------------------------------------------------------------------- | ||
+ | |||
+ | ijoffset: | ||
+ | mov ecx, width ;Number of columns | ||
+ | mul ecx ;eax<-row # * number of columns | ||
+ | add eax,ebx ;eax<-row# * # of columns + column # | ||
+ | ret | ||
+ | |||
+ | |||
</pre></code> | </pre></code> |
Latest revision as of 09:45, 29 October 2008
Exercises on Conditional Jumps
Contents
Finding the minimum
Find the minimum of 3 signed int variables a, b, and c
section .data
a dd 3
b dd 5
c dd 1
min dd 0
section .text
global _start
_start:
;;; if a <= b: # if1
;;; if a <= c: # if2
;;; min = a #
;;; else: # a > c # else2
;;; min = c
;;; else: # a > b # else1
;;; if b >= c: # if3
;;; min = c
;;; else: # b < c # else3
;;; min = b
mov eax, dword[a]
mov ebx, dword[b]
mov ecx, dword[c]
if1: cmp eax, ebx
jg else1
if2 cmp eax, ecx
jg else2
mov dword[min], eax
jmp done
else2: mov dword[min], ecx
jmp done
else1:
if3: cmp ebx, ecx
jl else3
mov dword[min], ecx
jmp done
else3: mov dword[min], ebx
done:
Loop until overflow
Print fibonacci numbers coded as unsigned words until the result overflows. Don't print erroneous numbers!
3 Solution programs:
- FibOverflowByte.asm: using an array of bytes
fib(2) = 2 fib(3) = 3 fib(4) = 5 fib(5) = 8 fib(6) = 13 fib(7) = 21 fib(8) = 34 fib(9) = 55 fib(10) = 89
- FibOverflowWord.asm: using an array of words
fib(2) = 2 fib(3) = 3 fib(4) = 5 fib(5) = 8 fib(6) = 13 ... fib(19) = 6765 fib(20) = 10946 fib(21) = 17711 fib(22) = 28657
- FibOverflowDWord.asm: using an array of dwords
fib(2) = 2 fib(3) = 3 fib(4) = 5 fib(5) = 8 ... fib(43) = 701408733 fib(44) = 1134903170 fib(45) = 1836311903
All 3 programs require
Scanning an array
- Find the largest element of a 1-dimensional array of signed double-words.
section .data
msg1 db "large of array = ",0
array dd 1, 3, 10, 0, -2, 44, 10
N equ ($-array)/4
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
;;; ---------------------------------------------------------
;;; main program
;;; ---------------------------------------------------------
asm_main:
;;; largest = MOSTNEG;
;;; for ( i=0; i<N; i++ ) {
;;; if ( array[i]>largest )
;;; largest = array[i];
;;;
;;; print "largest of array = ", largest
mov esi, 0
mov ebx, 0x80000000 ; most negative dword
for: cmp esi, N*4
jge done
cmp ebx, dword[array+esi]
jg next
mov ebx, dword[array+esi]
next: add esi, 4
jmp for
done:
mov eax, ebx
call printMax
ret
;;; ----------------------------------------------------------
;;; printMax: gets integer in eax and prints it
;;; ----------------------------------------------------------
printMax:
push eax ; save max in stack
mov eax, msg1
call print_string ; prints " "
pop eax ; get max from stack
call print_int ; print fact(i)
call print_nl ; next line
ret
- Same question, but with unsigned double words.
- For unsigned double words, then change the definition of the array (so that it does not contain negative numbers), and replace the jg next instruction by ja next instruction.
Characters and lower/upper case conversion
The program makeUpper.asm transforms all characters in a string to uppercase, but will also transform other characters that are not letters.
Modify the program so that it modifies only characters between 'a' and 'z' included.
;;; makeUpper.asm
;;; D. Thiebaut
;;;
;;; transforms a string to its uppercase equivalent
;;; (works only if the string contains only letters)
;;;
;;; nasm -f elf xxxx.asm
;;; gcc -o xxxx driver.c asm_io.o xxxx.o
;;;
%include "asm_io.inc"
;; -------------------------
;; data segment
;; -------------------------
section .data
str1 db "NabucoDonoSOR was king of Babylon!!!",0
STR1LEN equ $-str1-1
MASK equ 32
section .bss
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
;;;--- print the original string ---
mov eax,str1
call print_string
call print_nl
;;;--- force characters to uppercase ---
mov ebx,str1
mov ecx,STR1LEN
mov ah, MASK
not ah
for: mov al, byte[ebx]
cmp al, 'a'
jb next
cmp al, 'z'
ja next
and byte[ebx], ah
next:
inc ebx
loop for
;;;--- print new string ---
mov eax,str1
call print_string
call print_nl
;; return to C program
ret
Long/short jumps
Conditional jumps can jump only +127 bytes down, -128 bytes up in the code. How can we code something like this:
cmp eax,10 jl there ... ... there: ...
when the instruction at Label there is 1000 bytes away from the jl conditional jump?
cmp eax,10
jge next
jmp there
next:
...
...
there: ...
Print 2-dimensional arrays
Write the code necessary for printing an array of chars (maze) using for-loops depending on i and j indexes.
;;; ------------------------------------------------------------
;;; data areas
;;; ------------------------------------------------------------
section .data
maze db "################################"
maze2 db " # # # "
db "######### # # ####### # #"
db "# # # # #"
db "######### ##############"
db "# #### #"
db "################################"
width equ maze2-maze ; num of columns
height equ 7 ; num of rows
i dd 0
j dd 0
A solution...
;;; -----------------------------------------------------------------------
;; printMaze: prints the maze in the maze variable
;; Nothing needs to be passed
;;; -----------------------------------------------------------------------
printMaze:
initfori1:
mov dword[i],0 ;Start at 1st row
mov ecx,height ;Loop once for each row
fori1: push ecx ;Store loop counter
intiforj1:
mov dword[j],0 ;1st column
mov ecx,width ;Loop once for each column
forj1:
push ecx
;; Get ready to call offset fn
mov eax, [i]
mov ebx, [j]
call ijoffset
mov al, byte[maze+eax] ;Get correct character in maze
call print_char
inc dword[j] ;go to next column
pop ecx ;Retrieve loop counter
loop forj1
call print_nl
pop ecx
inc dword[i] ;next row
loop fori1
ret
;;; -----------------------------------------------------------------------
;; ijoffset: gets a coordinate in the maze, taking the row # from eax
;; and the column # from ebx, and calculates the
;; appropriate offset and stores it in eax.
;; uses eax, ebx, ecx
;;; -----------------------------------------------------------------------
ijoffset:
mov ecx, width ;Number of columns
mul ecx ;eax<-row # * number of columns
add eax,ebx ;eax<-row# * # of columns + column #
ret