Assembly Program for Printing an Unsigned Integer
Assignment: Quiz 10
Write a program printuint.s that prints the unsigned value stored in its data segment at label n. So a skeleton for this program is given by
1 2 3 4 5 6 7 8 9 10 | .data
.align 8
n .quad 0x123456789ABCDEF
.text
/*
Your code that prints the unsigned byte at label n
*/
|
On theon submit your instruction set isa.txt and program with the following command
1 | submit hpc quiz10 isa.txt printuint.s
|
C as kind of Pseudo-Code
This C code basically reflects how an assembly implementation can be realized. It intensionally has some expressions that normally might not use in this form. C. However, in this way it provides some opportunity to you for reviewing a view things in C ;-)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include <stdio.h>
// for: int putchar(int);
unsigned long long n = 0x123456789ABCDEF;
char buf[20];
int
main()
{
// local variables are used as registers (the compiler will actually use
// registers here if you compiler with -O1)
unsigned long long val;
char digit;
char *p;
// fetch variable n into val
val = n;
// p point to begin of buf array
p = buf;
do {
digit = val % 10 + '0';
val /= 10;
// store ASCII value of digit at *p then increment pointer
*(p++) = digit;
} while (val != 0);
// print stored characters
for (; p != buf; putchar(*--p)) {
}
// print extra newline (not needed for quiz)
putchar('\n');
}
|
Test Run after Compiling with gcc
theon$ gcc -Wall -o printuint-gcc printuint.c theon$ printuint-gcc 81985529216486895 theon$
Test Run after Compiling with ucc
theon$ ucc -o printuint-ucc printuint.c theon$ printuint-ucc 81985529216486895 theon$
Provided Material
You can use this ULM Instruction Set for Quiz 11. Here its isa.txt source code:
RRR (OP u 8) (X u 8) (Y u 8) (Z u 8)
J26 (OP u 8) (XYZ j 24)
U16R (OP u 8) (XY u 16) (Z u 8)
0x01 RRR
: halt %X
ulm_halt(ulm_regVal(X));
0x02 RRR
: getc %X
ulm_setReg(ulm_readChar() & 0xFF, X);
0x03 RRR
: putc %X
ulm_printChar(ulm_regVal(X) & 0xFF);
0x04 J26
: jmp XYZ
ulm_unconditionalRelJump(XYZ);
0x05 RRR
: subq X, %Y, %Z
ulm_sub64(X, ulm_regVal(Y), Z);
0x06 J26
: jnz XYZ
: jne XYZ
ulm_conditionalRelJump(ulm_statusReg[ULM_ZF] == 0, XYZ);
0x07 J26
: jz XYZ
: je XYZ
ulm_conditionalRelJump(ulm_statusReg[ULM_ZF] == 1, XYZ);
0x08 U16R
: ldzwq XY, %Z
ulm_setReg(XY, Z);
0x09 RRR
: movzbq (%X), %Z
ulm_fetch64(0, X, 0, 0, ULM_ZERO_EXT, 1, Z);
0x0A RRR
: addq X, %Y, %Z
ulm_add64(X, ulm_regVal(Y), Z);
0x0B RRR
: imulq %X, %Y, %Z
ulm_mul64(ulm_regVal(X), ulm_regVal(Y), Z);
0x0C J26
: ja XYZ
ulm_conditionalRelJump(ulm_statusReg[ULM_ZF] == 0
&& ulm_statusReg[ULM_CF] == 0, XYZ);
0x0D J26
: jb XYZ
ulm_conditionalRelJump(ulm_statusReg[ULM_CF] == 1, XYZ);
0x0E RRR
: addq %X, %Y, %Z
ulm_add64(ulm_regVal(X), ulm_regVal(Y), Z);
0x0F RRR
: imulq X, %Y, %Z
ulm_mul64(X, ulm_regVal(Y), Z);
0x10 RRR
# Uses the 128-bit unsigned integer divider. The 64-bits stored in %Y are
# therefore zero extended with %0 to 128 bits and then used as numerator.
# The immediate value X is used as unsigned denominator.
#
# The result of the operation is the quotient and the remainder. These results
# will be stored in a register pair: The quotient is stored in %Z and the
# remainder in %{Z + 1}.
: divq X, %Y, %Z
ulm_div128(X, ulm_regVal(Y), ulm_regVal(0), Z, 0, Z + 1);
0x11 RRR
# The least significant byte in %X gets stored at address %Z.
: movb %X, (%Z)
ulm_store64(0, Z, 0, 0, 1, X);
0x12 RRR
# Fetches a quad word from address %X into register %Z
: movq (%X), %Z
ulm_fetch64(0, X, 0, 0, ULM_ZERO_EXT, 8, Z);
# General meaning of the mnemonics
@addq
# Integer addition.
@getc
# Get character
@divq
# 64-bit unsigned integer division
@halt
# Halt program
@imulq
# 64-bit unsigned and signed integer multiplication.
@ja
# Jump if above (conditional jump).
@jb
# Jump if below (conditional jump).
@je
# Jump if equal (conditional jump).
@jmp
# Jump (unconditional jump).
@jne
# Jump if not equal (conditional jump).
@jnz
# Jump if not zero (conditional jump).
@jz
# Jump if zero (conditional jump).
@ldzwq
# Load zero extended word to quad word register.
@putc
# Put character
@subq
# Integer subtraction.
@movb
# Move a byte from a register to memory (store instruction).
@movzbq
# Move zero extended byte to quad word register (fetch instruction).
@movq
# Move quad word
Compared to the last session three instructions were added:
-
The instruction divq X, %Y, %Z computes the quotient and remainder of an unsigned integer division. Note that the two results are stored in the register pair %Z and %{Z + 1}:
\[\begin{array}{lcl}\left\lfloor \frac{u(\%Y)}{u(X)} \right\rfloor & \to & u(\%Z)\\u(\%Y) \bmod u(X) & \to & u(\%\{Z + 1\})\\\end{array}\] -
The instruction movb %X, (%Y) can be used to store the least significant byte in %X at address %Y:
\[u(\%X) \bmod 2^8 \to u(M_1(a))\;\text{with}\;a = u(\%Y)\] -
The instruction movq (%X), %Y can be used to fetch a quad word from address %X into register %Y:
\[u(M_8(a)) \to u(\%Y)\;\text{with}\;a = u(\%X)\]