Laboratory 3 - complex arithmetic expressions
In this lab: complex arithmetic expressions (additions, subtractions, multiplications, divisions, conversions, variable declarations).
Theory
Arithmetic instructions
- ADC - Add with Carry,
- SBB - Integer Subtraction with Borrow,
- IMUL - Signed Multiply,
- IDIV - Signed Divide.
Signed conversion instructions
- CBW - Convert Byte to Word
- CWD - Convert Word to Doubleword (DX:AX ← sign-extend of AX)
- CWDE - Convert Word to Doubleword (EAX ← sign-extend of AX)
- CDQ - Convert Doubleword to Quadword (EDX:EAX ← sign-extend of EAX)
Unsigned conversions
There are no instructions for conversions in the unsigned representation! In assembly language, the unsigned conversions are done by putting 0 in the high byte, word or doubleword:
mov AH,0 ; for converting AL → AX
mov DX,0 ; for converting AX → DX:AX
mov EDX,0 ; for converting EAX → EDX:EAX
Declaring variables / constants
- Declaring variables and assigning an initial value:
a DB 0A2h ;declaring the variable a of type BYTE and initialising it with the value 0A2h
b DW 'ab' ;declaring the variable a of type WORD and initialising it with the value 'ab'
c DD 12345678h ;declaring the variable a of type DOUBLE WORD and initialising it with the value 12345678h
d DQ 1122334455667788h ;declaring the variable a of type QUAD WORD and initialising it with the value 1122334455667788h
- Declaring variables without assignment (reserve space in memory):
a RESB 1 ;reserving 1 byte
b RESB 64 ;reserving 64 bytes
c RESW 1 ;reserving 1 word
- Defining constants:
ten EQU 10 ;defining the constant ten that has the value 10
Notations
<op8> - operand on 8 bits
<op16> - operand on 16 bits
<op32> - operand on 32 bits
<reg8> - register on 8 bits
<reg16> - register on 16 bits
<reg32> - register on 32 bits
<reg> - register
<regd> - destination register
<regs> - source register
<mem8> - memory variable on 8 bits
<mem16> - memory variable on 16 bits
<mem32> - memory variable on 32 bits
<mem> - memory variable
<con8> - constant (immediate value) on 8 bits
<con16> - constant (immediate value) on 16 bits
<con32> - constant (immediate value) on 32 bits
<con> - constant (immediate value)
Little endian representation
- Each byte has an address (the byte being the smallest addressable unit of memory)
- An address identifies in a unique way a location in memory, and x86 processors assign each byte location a separate memory address
- x86 processors store and retrieve data from memory using little endian order (the byte representing the „end” of the number will be stored at the „little”-est address):
- The least significant byte is stored at the beginning of that memory area (at the address where allocation for the data begins).
- The remaining bytes are stored in reverse order in the next consecutive memory positions.
(much more clearer as an informal statement: if we have on paper or in a register a 4 bytes number and we denote the order of these bytes as 1 2 3 4 , in the memory the little-endian representation will store that number in the reverse order of its bytes: 4 3 2 1).
Careful ! – only the BYTES order is reversed in memory, NOT the BITS inside that bytes !!!!! The order of the bits which compose each byte remains the same !
For instance, if we have the following data segment:
a db 12h
b dw 3456h
c dd 7890abcdh
d dq 1122334455667788h
Data representation in memory will be as shown in the lowest left corner from the below debugger configuration:
Example 1: Addition: quadword+quadword
bits 32 ;assembling for the 32 bits architecture
; the start label will be the entry point in the program
global start
extern exit ; we inform the assembler that the exit symbol is foreign, i.e. it exists even if we won't be defining it
import exit msvcrt.dll; exit is a function that ends the process, it is defined in msvcrt.dll
; msvcrt.dll contains exit, printf and all the other important C-runtime functions
segment data use32 class=data ; the data segment where the variables are declared
a dq 1122334455667788h
b dq 0abcdef1a2b3c4d5eh
r resq 1 ; reserve 1 quadword in memory to save the result
; our code starts here
segment code use32 class=code ; code segment
start:
;11223344 55667788 h -> EDX : EAX
; EDX : EAX
mov eax, dword [a+0]
mov edx, dword [a+4]
; abcdef1a 2b3c4d5e h -> ECX : EBX
; ECX : EBX
mov ebx, dword [b+0]
mov ecx, dword [b+4]
;a + b
; edx : eax +
; ecx : ebx
clc ; clear Carry Flag (punem 0 in CF)
add eax, ebx ; eax= eax+ebx
adc edx, ecx ; edx = edx+ecx + CF
;(CF is set is add eax, ebx produce a carry)
;edx:eax -> r
mov dword [r+0], eax
mov dword [r+4], edx
push dword 0 ; push the parameter for exit onto the stack
call [exit] ; call exit to terminate the program
Step 1 – before perform the addition
Step 2 – after addition
Example 2. Division: quadword/doubleword
bits 32 ;assembling for the 32 bits architecture
; the start label will be the entry point in the program
global start
extern exit ; we inform the assembler that the exit symbol is foreign, i.e. it exists even if we won't be defining it
import exit msvcrt.dll; exit is a function that ends the process, it is defined in msvcrt.dll
; msvcrt.dll contains exit, printf and all the other important C-runtime functions
segment data use32 class=data ; the data segment where the variables are declared
m dq 1122334455667788h
n dd 0ccddeeddh
rezd resd 1
; our code starts here
segment code use32 class=code ; code segment
start:
mov ebx, [n]
;11223344 55667788 h -> EDX : EAX
; EDX : EAX
mov eax, dword [m+0]
mov edx, dword [m+4]
div ebx ; edx:eax/ebx=eax cat si edx rest
mov dword[rezd], eax
push dword 0 ; push the parameter for exit onto the stack
call [exit] ; call exit to terminate the program
Debugger
Example - arithmetic expressions
Unsigned representation
; Write a program in assembly language which computes one of the following arithmetic expressions, considering the following domains for the variables:
; a - doubleword; b, d - byte; c - word; e - qword
; a + b / c - d * 2 - e
bits 32 ;assembling for the 32 bits architecture
; the start label will be the entry point in the program
global start
extern exit ; we inform the assembler that the exit symbol is foreign, i.e. it exists even if we won't be defining it
import exit msvcrt.dll; exit is a function that ends the process, it is defined in msvcrt.dll
; msvcrt.dll contains exit, printf and all the other important C-runtime functions
segment data use32 class=data ; the data segment where the variables are declared
a dd 125
b db 2
c dw 15
d db 200
e dq 80
segment code use32 class=code ; code segment
start:
;for computing b/c, we convert b from byte to doubleword, so that we can divide it by the word c
mov al, [b]
mov ah, 0 ;unsigned conversion from al to ax
mov dx, 0 ;unsigned conversion from ax to dx:ax
;dx:ax = b
div word [c] ;unsigned division dx:ax by c
;ax=b/c
;catul impartirii este in ax (restul este in dx, dar mergem mai departe doar cu catul)
mov bx, ax ;we save b/c in bx so that we can use ax for multiplying d by 2
mov al, 2
mul byte [d] ;ax=d*2
sub bx, ax ;bx = b / c - d * 2
; we convert the word bx to doubleword so that we can add it with the doubleword a
mov cx, 0 ; unsigned conversion from bx to cx:bx
;cx:bx=b/c-d*2
mov ax, word [a]
mov dx, word [a+2] ;dx:ax=a
add ax, bx
adc dx, cx ;dx:ax = a + b / c - d * 2
push dx
push ax
pop eax ;eax = a + b / c - d * 2
mov edx, 0 ;edx:eax = a + b / c - d * 2
sub eax, dword [e]
sbb edx, dword [e+4] ;edx:eax = a + b / c - d * 2 - e
push dword 0 ;saves on stack the parameter of the function exit
call [exit] ; function exit is called in order to end the execution of the program
Signed representation
; Write a program in the assembly language that computes the following arithmetic expression, considering the following data types for the variables:
; a - doubleword; b, d - byte; c - word; e - qword
; a + b / c - d * 2 - e
bits 32 ;assembling for the 32 bits architecture
; the start label will be the entry point in the program
global start
extern exit ; we inform the assembler that the exit symbol is foreign, i.e. it exists even if we won't be defining it
import exit msvcrt.dll; exit is a function that ends the process, it is defined in msvcrt.dll
; msvcrt.dll contains exit, printf and all the other important C-runtime functions
segment data use32 class=data ; the data segment where the variables are declared
a dd 125
b db 2
c dw 15
d db 200
e dq 80
segment code use32 class=code ; code segment
start:
;for computing b/c, we convert b from byte to doubleword, so that we can divide it by the word c
mov al, [b]
cbw ;signed conversion from al to ax
cwd ;signed conversion from ax to dx:ax
;dx:ax = b
idiv word [c] ;signed division dx:ax by c
;ax=b/c
;the quotient of the division is in ax (the remainder is in dx, but we only use the quotient in the further computations)
mov bx, ax ;we save b/c in bx so that we can use ax for multiplying d and 2
mov al, 2
imul byte [d] ;ax=d*2
sub bx, ax ;bx=b/c-d*2
; we convert the word bx to doubleword so that we can add it with the doubleword a
mov ax, bx
cwd ; signed conversion from ax to dx:ax
;dx:ax=b/c-d*2
mov bx, word [a]
mov cx, word [a+2] ;cx:bx=a
add ax, bx
adc dx, cx ;the result of a + b / c - d * 2 is in dx:ax
push dx
push ax
pop eax ;eax = a + b / c - d * 2
cdq ;edx:eax = a + b / c - d * 2
sub eax, dword [e]
sbb edx, dword [e+4] ;edx:eax = a + b / c - d * 2 - e
push dword 0 ;saves on stack the parameter of the function exit
call [exit] ; function exit is called in order to end the execution of the program
Problems
Write a program in assembly language that computes one of the following arithmetic expressions, considering the following domains for the variables (in the unsigned and signed representation).
Additions, subtractions
a - byte, b - word, c - double word, d - qword - Unsigned representation
- c-(a+d)+(b+d)
- (b+b)+(c-a)+d
- (c+d)-(a+d)+b
- (a-b)+(c-b-d)+d
- (c-a-d)+(c-b)-a
- (a+b)-(a+d)+(c-a)
- c-(d+d+d)+(a-b)
- (a+b-d)+(a-b-d)
- (d+d-b)+(c-a)+d
- (a+d+d)-c+(b+b)
- (d-c)+(b-a)-(b+b+b)
- (a+b+d)-(a-c+d)+(b-c)
- d-b+a-(b+c)
- (a+d)-(c-b)+c
- a+b-c+(d-a)
- c-a-(b+a)+c
- (c+c-a)-(d+d)-b
- (d+d)-a-b-c
- (d+d)-(a+a)-(b+b)-(c+c)
- (a+c)-b+a + (d-c)
- (c-a) + (b - d) +d
- (d+c) - (c+b) - (b+a)
- ((a + a) + (b + b) + (c + c)) - d
- ((a + b) + (a + c) + (b + c)) - d
- (a + b + c) - (d + d) + (b + c)
- (c-b+a)-(d+a)
- (a+c)-(d+b)
- d-(a+b)+(c+c)
- d+c-b+(a-c)
- (b+c+a)-(d+c+a)
a - byte, b - word, c - double word, d - qword - Signed representation
- (c+b+a)-(d+d)
- (c+b)-a-(d+d)
- (b+b+d)-(c+a)
- (b+b)-c-(a+d)
- (c+b+b)-(c+a+d)
- c-(d+a)+(b+c)
- (c+c+c)-b+(d-a)
- (b+c+d)-(a+a)
- a-d+b+b+c
- b+c+d+a-(d+c)
- d-(a+b+c)-(a+a)
- (a-b-c)+(d-b-c)-(a-d)
- (b-a+c-d)-(d+c-a-b)
- c-b-(a+a)-b
- c+a+b+b+a
- (d-a)-(a-c)-d
- (c+d-a)-(d-c)-b
- (d-b)-a-(b-c)
- (d+a)-(c-b)-(b-a)+(c+d)
- a-b-(c-d)+d
- d-a+(b+a-c)
- c+b-(a-d+b)
- a + b + c + d - (a + b)
- (a + b + c) - d + (b - c)
- (a + b - c) + (a + b + d) - (a + b)
- (c-d-a)+(b+b)-(c+a)
- (d+d-c)-(c+c-a)+(c+a)
- c+d-a-b+(c-a)
- (a+a)-(b+b)-(c+d)+(d+d)
- d-a+c+c-b+a
Multiplications, divisions - Unsigned representation and signed representation
- c+(a*a-b+7)/(2+a), a-byte; b-doubleword; c-qword
- 2/(a+b*c-9)+e-d; a,b,c-byte; d-doubleword; e-qword
- (8-a*b*100+c)/d+x; a,b,d-byte; c-doubleword; x-qword
- (a*2+b/2+e)/(c-d)+x/a; a-word; b,c,d-byte; e-doubleword; x-qword
- (a+b/c-1)/(b+2)-x; a-doubleword; b-byte; c-word; x-qword
- x+a/b+c*d-b/c+e; a,b,d-byte; c-word; e-doubleword; x-qword
- (a-2)/(b+c)+a*c+e-x; a,b-byte; c-word; e-doubleword; x-qword
- 1/a+200*b-c/(d+1)+x/a-e; a,b-word; c,d-byte; e-doubleword; x-qword
- (a-b+c*128)/(a+b)+e-x; a,b-byte; c-word; e-doubleword; x-qword
- d-(7-a*b+c)/a-6+x/2; a,c-byte; b-word; d-doubleword; x-qword
- (a+b)/(2-b*b+b/c)-x; a-doubleword; b,c-byte; x-qword
- (a*b+2)/(a+7-c)+d+x; a,c-byte; b-word; d-doubleword; x-qword
- x-(a+b+c*d)/(9-a); a,c,d-byte; b-doubleword; x-qword
- x+(2-a*b)/(a*3)-a+c; a-byte; b-word; c-doubleword; x-qword
- x-(a*b*25+c*3)/(a+b)+e; a,b,c-byte; e-doubleword
- x/2+100*(a+b)-3/(c+d)+e*e; a,c-word; b,d-byte; e-doubleword; x-qword
- x-(a*a+b)/(a+c/a); a,c-byte; b-doubleword; x-qword
- (a+b*c+2/c)/(2+a)+e+x; a,b-byte; c-word; e-doubleword; x-qword
- (a+a+b*c*100+x)/(a+10)+e*a; a,b,c-byte; e-doubleword; x-qword
- x-b+8+(2*a-b)/(b*b)+e; a-word; b-byte; e-doubleword; x-qword
- (a*a/b+b*b)/(2+b)+e-x; a-byte; b-word; e-doubleword; x-qword
- a/2+b*b-a*b*c+e+x; a,b,c-byte; e-doubleword; x-qword
- (a*b-2*c*d)/(c-e)+x/a; a,b,c,d-byte; e-word; x-qword
- a-(7+x)/(b*b-c/d+2); a-doubleword; b,c,d-byte; x-qword
- (a*a+b+x)/(b+b)+c*c; a-word; b-byte; c-doubleword; x-qword
- (a*a+b/c-1)/(b+c)+d-x; a-word; b-byte; c-word; d-doubleword; x-qword
- (100+a+b*c)/(a-100)+e+x/a; a,b-byte; c-word; e-doubleword; x-qword
- x-(a*100+b)/(b+c-1); a-word; b-byte; c-word; x-qword
- (a+b)/(c-2)-d+2-x; a,b,c-byte; d-doubleword; x-qword
- a*b-(100-c)/(b*b)+e+x; a-word; b,c-byte; e-doubleword; x-qword