Lab 2: User Input and Arithmetic
Table of Contents
Overview
Your company is programming an embedded device that can manually adjust the settings of laboratory equipment. The technicians will type in a value using a terminal and then receive an output depending on how the machine responds.
You will learn about user input and basic calculations in NASM.
Sources
Introduction to NASM Programming - University of Hawaii Presentation
NASM: data and bss (inverted) - University of Hawaii Presentation
x86 Assembly Language Programming - Ray Toal
X86 Assembly/Arithmetic - Wikibooks
Registers and Pointers
Recall in C that you can work with the value directly or work with a value at a specific memory location.
&
gets the address of the variable.
*
get the value of the variable at the memory location.Consider this code block:
int x = 5; // Assign x to a value int *address = &x; // Get the address of x printf("Value of 'x': = %d; \n", x); printf("Address of 'x' = %p \n", address); printf("Contents at address = %d; ", *address); /* Output: Value of 'x': = 5; Address of 'x' = 0x7ffc62289f14 Contents at address = 5; */
ASM operates in a similar way. See slides 22 and 24 in Introduction to NASM Programming.
mov eax, 5 ; places the value of 5 in register EAX ; eax = 5 mov ecx, [eax] ; places the contents at the address of EAX in ECX ; ecx = *eax
Reserving Memory
The programmer is responsible for reserving to prevent a
segmentation fault and other errors. There are two types of data
directives in an ASM file to reserve memory, which DX
and RESX
.
The X
refers to the data size.
Unit |
Letter (X) |
Size in bytes |
---|---|---|
byte |
b |
1 |
word |
w |
2 |
double word |
d |
4 |
quad word |
q |
8 |
ten bytes |
t |
10 |
DX directives: Initialized Data (D = “defined”)
Memory is reserved in the DX block using the three elements:
label - An unquoted text string
d
+ memory unitinitial value
L1 db 0x55 ; just the byte 0x55
L2 db 0x55,0x56,0x57 ; three bytes in succession
L3 db 'a',0x55 ; character constants are OK
L4 db 'hello',13,10,'$' ; so are string constants
L5 dw 0x1234 ; 0x34 0x12
L6 dw 'a' ; 0x61 0x00 (it's just a number)
L7 dw 'ab' ; 0x61 0x62 (character constant)
L8 dw 'abc' ; 0x61 0x62 0x63 0x00 (string)
L9 dd 0x12345678 ; 0x78 0x56 0x34 0x12
L10 dd 1.234567e20 ; floating-point constant
L11 dq 0x123456789abcdef0 ; eight byte constant
L12 dq 1.234567e20 ; double-precision float
L13 dt 1.234567e20 ; extended-precision float
RESX directives: Uninitialized Data (RES = “reserved”)
Memory is reserved in the RESX block using the three elements:
label - An unquoted text string
res
+ memory unitmemory to reserve
buffer: resb 64 ; reserve 64 bytes
wordvar: resw 1 ; reserve a word
realarray: resq 10 ; array of ten reals (floats)
Task 1: Setup your Project
Create your project directory,
input.asm
file, andMakefile
.Use NASM Template to help you get started.
Tip
Create a template folder that you can replicate for each project.
# Create a copy for a new project
cd ~/asm
cp -r template lab2
Task 2: Prompt for Input and Print the values
You will verify that your program can read in a value and display it.
Use Introduction to NASM Programming and NASM: data and bss (inverted) to help you.
Display a message to the user to input a value. The string to print goes in the
.data
segment.Read the input using
read_int
, which get put in register EAX.call read_int ; read_int puts the value in EAX
Print the value using
print_int
Enter a value: 358 358
Note
The value resides in EAX, but we will lose the value if we don’t store it in memory.
Create a label for the input value in the
.bss
segment and reserve memory for a 32-bit value, which is 4 bytes or adouble word
.Call the label
VAL1
Choose a method to reserve 32 bits
VAL1 resd 1 ; reserve a single double word VAL1 resb 4 ; reserve 4 bytes
Store the value in EAX in memory using the address at VAL1.
Note
This operation works with the memory address, similar to how C uses a pointer with
scanf
.char *input; // Get pointer to a single byte scanf("%s",&input); // Read a single byte and store in memory
You would do this in ASM:
mov [VAL1], eax
Prompt the user for a second value and store it in memory using a label called
VAL2
.Print the first value that label
VAL1
references. You must first move the value to EAX.mov eax, [VAL1]
Verify that you can input and output the full range of signed 32-bit values. Then, try entering more data than can fit in a 32-bit register (EAX).
; Minimum range
Enter a value: 1
Enter a value: -1
1
-1
; Maximum range
Enter a value: 2147483647
Enter a value: -2147483648
2147483647
-2147483648
; Values too large for the register are truncated
Enter a value: 9999999999
Enter a value: -9999999999
2147483647
-2147483648
Task 3: Addition an Subtraction
Your program now accepts user input, stores the value in memory, and then prints the value to the screen.
It more interesting to do something with the data instead of reprinting the input.
Tip
Move the data to a register to manipulate it.
Use registers
EAX
,ECX
, andEDX
for general use or scratch registers.
Here is a quick list of use NASM commands for manipulating data.
Command |
Stored Result |
---|---|
mov x, y |
x ← y |
and x, y |
x ← x and y |
or x, y |
x ← x or y |
xor x, y |
x ← x xor y |
add x, y |
x ← x + y |
sub x, y |
x ← x – y |
inc x |
x ← x + 1 |
dec x |
x ← x – 1 |
Move the value in
VAL1
to ECX.Move the value in
VAL2
to EDX.Increment the first input placed in ECX.
Decrement the second input placed in EDX.
Print the results.
Note
You will have to move the values to EAX to print them
Enter a value: 10 Enter a value: 20 10 ; [VAL1] 20 ; [VAL2] 11 ; [VAL1]++ 19 ; [VAL2]--
Add the two values together and store the value in
RESX
with a label ofRESULT
.Print the value in
RESULT
.Enter a value: 10 Enter a value: 20 10 ; [VAL1] 20 ; [VAL2] 11 ; [VAL1]++ 19 ; [VAL2]-- 30 ; [RESULT] = [VAL1] + [VAL2]
Subtract
VAL1
orVAL2
fromRESULT
and verify that value matches the original. You can calldump_regs 0
to view the contents of the registers.Enter a value: 10 Enter a value: 20 10 ; [VAL1] 20 ; [VAL2] 11 ; [VAL1]++ 19 ; [VAL2]-- 30 ; [RESULT] = [VAL1] + [VAL2] 11 ; [RESULT] = [RESULT] - [VAL2] Register Dump # 0 EAX = 0000000B EBX = 56649FCC ECX = 0000000B EDX = 00000013 ESI = F7FAF000 EDI = 00000000 EBP = FFD870C8 ESP = FFD870A8 EIP = 56648851 FLAGS = 0202
Task 4: Multiplication and Division
You should have a good feel for working with registers and RESX directives. Now, we can do more complex operations by performing multiplication and division.
Note
Take note of the specific registers in the table.
The operations stores the result in register
EAX
, but use registerEDX
to store additional data.
Command |
Stored Result |
Notes |
---|---|---|
|
eax ← eax * eax |
|
|
eax ← eax * x |
|
|
eax ← eax / ecx |
Divides EAX by the value in the register by EAX. |
Note
You should clear register EDX before performing a multiplication or division operation.
Multiply the value in EAX by the value in
VAL1
and print the results.Note: You need to put
VAL1
in register ECX.Enter a value: 10 Enter a value: 20 10 ; [VAL1] 20 ; [VAL2] 11 ; [VAL1]++ 19 ; [VAL2]-- 30 ; [RESULT] = [VAL1] + [VAL2] 11 ; [RESULT] = [RESULT] - [VAL2] 110 ; [RESULT] = EAX * [VAL1] Register Dump # 0 EAX = 0000006E EBX = 56580FCC ECX = 0000000A EDX = 00000000 ESI = F7EC7000 EDI = 00000000 EBP = FFBB11E8 ESP = FFBB11C8 EIP = 5657F878 FLAGS = 0202
Now, divide the value in EAX by the value in
VAL2
. Print the result of the division (EAX) and of the remainder (EDX).110 / 20 = 5, remainder 10
Note
Evaluate the results of
dump_regs
to see the parts equation and result.Enter a value: 10 Enter a value: 20 10 ; [VAL1] 20 ; [VAL2] 11 ; [VAL1]++ 19 ; [VAL2] -- 30 ; [RESULT] = [VAL1] + [VAL2] 11 ; [RESULT] = [RESULT] - [VAL2] 110 ; EAX = EAX * [VAL1] 5 ; EAX = EAX / [VAL2] 10 ; Remainder in EDX Register Dump # 0 EAX = 0000000A EBX = 5660DFCC ECX = 00000014 EDX = 0000000A ESI = F7F25000 EDI = 00000000 EBP = FF9939A8 ESP = FF993988 EIP = 5660C89B FLAGS = 0202