VNA: Control Structures
Content |
Warning On thales the ULM Assembler will not work! The installed gawk is to old! Use the Linux computers in E44. If you have your own Linux box you should have no problem. All Linux distributions have a decent gawk version.
If you want to login on a E44 computer via ssh:
-
first login on thales (ssh yourloginname@thales.mathematik.uni-ulm.de)
-
then login on a E44 computer, e.g. on heim with ssh heim (here you can skip the login name an the domain .mathematik.uni-ulm.de)
Update the ULM simulator (and obtain the assembler)
Change into the directory that contains ulm.cc (cloned from github in the previous session). Then update the source code for the simulator:
thales$ pwd /home/numerik/hpc/ss18/sessions/session01/ulm thales$ git pull Already up-to-date. thales$
Note that this will also download or update the ULM assembler (consisting of ulmas_label.awk and ulmas_codegen.awk).
If you don't get a message that the source code of ulm.cc was up-to-date you need to re-compile with
thales$ g++ -Wall -std=c++11 -o ulm ulm.cc thales$
Using the Assembler
The assembler consists of 3 awk scripts:
-
ulmas_macro.awk
Expands macro and .equ directives.
-
ulmas_label.awk
Resolves labels and encodes data directives.
-
ulmas_codegen.awk
Translates assembly instructions into machine code instructions.
You have to run these scripts in the given order. Splitting the assembler into different scripts has the advantage that you can observe intermediate results after each step.
Example
Create a file foo1_asm.s (in the directory with the ULM simulator and the assembler) with following content:
.equ pN 1 .equ N 2 .text orq $n, %0, %pN movzbq (%pN, %0), %N subq $1, %N, %0 ja then orq $0x0D, %0, %N # else then: jmp $0x02 orq $0x2A, %0, %N movb %N, (%pN, %0) .data n: .quad 0x8000000000000000
Generate machine code for the ULM with
heim$ cat foo1_asm.s | gawk -f ulmas_macro.awk | gawk -f ulmas_label.awk | gawk -f ulmas_codegen.awk 81 20 00 01 # 0000 : orq $0x20, %0, %1 1A 01 00 02 # 0004 : movzbq (%1, %0), %2 63 01 02 00 # 0008 : subq $1, %2, %0 99 00 00 02 # 000C : ja $2 81 0D 00 02 # 0010 : orq $0x0D, %0, %2 9A 00 00 02 # 0014 : jmp $0x02 81 2A 00 02 # 0018 : orq $0x2A, %0, %2 46 02 01 00 # 001C : movb %2, (%1, %0) 80 00 00 00 #-0020 00 00 00 00 #-0024 heim$
If you want to see intermediate results just stop after running a script:
-
Only expand macros and .equ directives:
heim$ cat foo1_asm.s | gawk -f ulmas_macro.awk .text orq $n, %0, %1 movzbq (%1, %0), %2 subq $1, %2, %0 ja then orq $0x0D, %0, %2 then: jmp $0x02 orq $0x2A, %0, %2 movb %2, (%1, %0) .data n: .quad 0x8000000000000000 heim$
-
Expand macros/.equ directives and also resolve labels and data directives:
heim$ cat foo1_asm.s | gawk -f ulmas_macro.awk | gawk -f ulmas_label.awk orq $0x20, %0, %1 movzbq (%1, %0), %2 subq $1, %2, %0 ja $2 orq $0x0D, %0, %2 jmp $0x02 orq $0x2A, %0, %2 movb %2, (%1, %0) 80 00 00 00 #-0020 00 00 00 00 #-0024 heim$
You can redirect the output (containing the machine code) into a file. For example, into foo1_asm.ulm:
heim$ cat foo1_asm.s | gawk -f ulmas_macro.awk | gawk -f ulmas_label.awk | gawk -f ulmas_codegen.awk > foo1_asm.ulm heim$
Or do both, print the output on the therminal and redirect it, with the tee command:
heim$ cat foo1_asm.s | gawk -f ulmas_macro.awk | gawk -f ulmas_label.awk | gawk -f ulmas_codegen.awk | tee foo1_asm.ulm 81 20 00 01 # 0000 : orq $0x20, %0, %1 1A 01 00 02 # 0004 : movzbq (%1, %0), %2 63 01 02 00 # 0008 : subq $1, %2, %0 99 00 00 02 # 000C : ja $2 81 0D 00 02 # 0010 : orq $0x0D, %0, %2 9A 00 00 02 # 0014 : jmp $0x02 81 2A 00 02 # 0018 : orq $0x2A, %0, %2 46 02 01 00 # 001C : movb %2, (%1, %0) 80 00 00 00 #-0020 00 00 00 00 #-0024 heim$
Exercise
Use the assembler on all the other examples from the lecture. Remember that you can print the exit code of a UNIX process with echo $?.
Exercise
You get the following assembly code when you pulled the ULM simulator and assembler from github:
.equ N 5 # Immediate value for vector length .equ I 1 # register for i .equ X 2 # address of x .equ RES 3 # register for res .equ TMP 4 # register for tmp .text load $0, %I # I = 0 load $x, %X # address of x[0] load $0, %RES # result = 0 jmp check # goto check loop: movzbq (%X, %I), %TMP # x[I] addq %TMP, %RES, %RES # result += x[I] addq $1, %I, %I # ++I check: subq $N, %I, %0 # If (I<N) jb loop # goto loop halt %RES # return result .data x: .byte 1 .byte 2 .byte 3 .byte 4 .byte 5
First analyse the code:
-
Make a sketch of the memory layout (text and data segment)
-
Understand what happens when the program gets executed
-
Predict the exit code
Then use the assembler to translate the assembly code into machine code. Use the simulator to run the program
Exercise
Write a assembly program that has the values 1, 2, 3, 4, 5 in the data segment as bytes and exits with the product of these numbers. You can use the assembly instruction mulq for multiplying registers. For example
mulq %1, %2, %3
multiplies register 1 with register 2 and stores the result in register 3.
Exercise
Write a assembly program that has the values 1, 2, 3, 4, 5 in the data segment as quad word and exits with the product of these numbers.
Exercise
Write a program that realizes the following pseudo code:
Global Variable: n (unsigned integer, size=1 byte) Main program: result = 1 for i=1,...,n: result <- result * i return result
Exercise
Write a program that realizes the following pseudo code:
Global Variable: n (unsigned integer, size=1 byte) Main program: result = 1 while n>1: result <- result * n n <- n-1 return result
Submit your Solution
Send your attached solution by Email to michael.lehn@uni-ulm.de. Use the subject HPC0: quiz01.
Deadline: May 4th, 2pm