210 likes | 291 Views
Practical Session 5. Addressing Modes. #include <stdio.h> #define VECTOR_SIZE 5 #define MATRIX_ROWS 2 #define MATRIX_COLUMNS 3 extern int DotProduct(int V1[VECTOR_SIZE], int V2[VECTOR_SIZE],int size); extern void MatrixVectorProduct (int M[MATRIX_ROWS * MATRIX_COLUMNS],
E N D
#include <stdio.h> #define VECTOR_SIZE 5 #define MATRIX_ROWS 2 #define MATRIX_COLUMNS 3 extern int DotProduct(int V1[VECTOR_SIZE], int V2[VECTOR_SIZE],int size); extern void MatrixVectorProduct (int M[MATRIX_ROWS * MATRIX_COLUMNS], int V[MATRIX_COLUMNS], int rows, int columns, int result[MATRIX_ROWS]);
int main () } int V1[VECTOR_SIZE] = {1,0,1,0,2}; int V2[VECTOR_SIZE] = {1,0,1,0,-2}; int result = DotProduct(V1,V2,VECTOR_SIZE); printf ("Dot product result: %d\n",result); // Vector: // {20 1 15} int V[MATRIX_COLUMNS] = {20,1,15}; // Matrix: // { 3 1 3} // {10 2 3} int M[MATRIX_ROWS * MATRIX_COLUMNS] = {3,1,3,10,2,3}; int result_vector[MATRIX_ROWS] = {0,0}; MatrixVectorProduct(M,V,MATRIX_ROWS,MATRIX_COLUMNS,result_vector); printf ("Matrix product result:"); int i; for (i = 0;i < MATRIX_ROWS;i = i + 1) printf (" %d",result_vector[i]); printf ("\n"); return 0; {
DotProduct: push ebp mov ebp, esp push ebx push ecx push edx mov ecx, 0 dot_start: mov edx, 0 cmp ecx, dword [ebp+16] je dot_end mov ebx, dword [ebp+8] mov eax, dword [ebx + (4*ecx)] mov ebx, dword [ebp+12] imul dword [ebx + (4*ecx)] add dword [result], eax inc ecx jmp dot_start dot_end: mov eax, dword [result] ; Return Value pop edx pop ecx pop ebx mov esp, ebp pop ebp ret section .data result: dd 0 section .text global DotProduct global MatrixVectorProduct:
MatrixVectorProduct: push ebp mov ebp, esp pushad mov esi, dword [ebp+24] mov ebx, 0 mv_row: cmp ebx, dword [ebp+16] ; Rows je mv_end mov ecx, 0 mv_column: cmp ecx, dword [ebp+20] ; Columns je mv_column_end mov eax, dword [ebp+20] ; MATRIX_COLUMNS mul ebx mov edi, eax ; row * MATRIX_COLUMNS mov edx, dword [ebp+8] ; M add edi, ecx ; (row * MATRIX_COLUMNS)+column mov eax, dword [edx + edi*4] ; M[row*(MATRIX_COLUMNS) + column] mov edx, dword [ebp+12] mul dword [edx + ecx*4] ; V[column] add dword [esi], eax inc ecx jmp mv_column mv_column_end: inc ebx add esi, 4 jmp mv_row mv_end: popad mov esp, ebp pop ebp ret
Linux System Calls • System calls are low level functions the operating system makes available to applications via a defined API (Application Programming Interface) • System calls represent the interface the kernel presents to user applications. • In Linux all low-level I/O is done by reading and writing file handles, regardless of what particual peripheral device is being accessed - a tape, a socket, even your terminal, they are all files • Low level I/O is performaned by making system calls
Anatomy of System Calls • A system call is explicit request to the kernel made via asoftware interrupt. • The interrupt call ‘0x80’ call to a system call handles. • To perform Linux system calls we have to do following: • Put the system call number in EAX register. • Set up the arguments to the system call in EBX,ECX, etc. • call the relevant interrupt (for DOS, 21h; for Linux, 80h). • The result is usually returned in EAX.
There are six registers that are used for the arguments that the system call takes. The first argument goes in EBX, the second in ECX, then EDX, ESI, EDI, and finally EBP. If more then 6 arguments needed (not likely), the EBX register must contain the memory location where the list of arguments is stored. • Files (in Linux everything is a file) are referenced by an integer file descriptor.
sys_write – write into a file • system call number (in EAX): 4 • arguments: • EBX: The file descriptor. • ECX: Pointer to the first byte to read (beginning of the string). • EDX: Number of bytes (characters) to write. • Returns in EAX: Number of bytes written. • On errors: -1.
sys_open - open a file • system call number (in EAX): 5 • arguments: • EBX: The pathname of the file to open/create • ECX: set file access bits (can be OR’d togather): • O_RDONLY open for reading only • O_WRONLY open for writing only • O_RDRW open for both reading and writing • O_APPEND open for appending to the end of file • O_TRUNC truncate to 0 length if file exists • O_CREAT create the file if it doesn’t exist • EDX: set file permissions (in case of create). • Returns in EAX: file descriptor. • On errors: -1.
section .data filename: db “file.ext", 0 Handle dd 0 section .text my_func: mov eax,5 mov ecx, 1 ; O_WRONLY mov ebx,filename int 0x80 inc eax ; eax = -1 on error jz error dec eax mov [Handle],eax jmp file_opened file_opened : …. ret error: … ret sys_open - open a file – an example
The Man 2 Pages • In Linux, there is a collection of manual pages specifically for system calls. • The collection number is 2. • In order to read about a specific system call, use the ‘Man’ command • Example: > man 2 openThis will show the manual pages for the ‘open’ system call.
Assigment #2 • Writing a simple calculator for unlimited-precision integers. • Operators: • Addition (+) • Pop-and-print (p) • Duplicate (d) • Divide (unsigned) (/) • Binary (b) • Hexadecimal (h) • Quit (q) • The calculator uses Reverse Polish Notation (RPN semantics) • Operands in the input and output will be in hexadecimal or binary - according to the setting (b/h)
Assigment #2 • With RPN every operator follows all of its operands, • For example: 1 2 + 1+2 2 3 * 2*3 4 1 2 + * 4*(1+2) • Operands in the calculator are implicit – taken from a stack • The stack data type is implemented by you
Assignment #2 Stack >>calc: 09 TOS -> 09 0A >>calc: 1 TOS -> 01 0A >>calc: d TOS -> 01 TOS -> >>calc: p >>01 >>calc: + >>calc: d >>calc: p >>0A
Assignment #2 Stack >>calc: 04 TOS -> 02 0A >>calc:/ TOS -> 04 >>calc: b TOS -> >>calc: p >>00000010 >>calc: + Error: Not Enough Arguments in Stack
Assignment #2 • Your program should be able to handle an unbounded operand size. • This type could be implemented as a linked list: • Each element represents 2 hexadecimal digits in the number. • An element block is composed of a 4 byte pointer to the next element, and a byte data. • For example, the number 0x7D12AF could be represented by the list: • Using this representation, each stack element is simply a list head pointer . AF 7D 0 12
Assignment #2 • Addition (+) is defined on signed operands; unlimited of length. • Div (/) is defined on unsigned operands; the divided (older element in stack) is unlimited in length whereas the divisor (on top-of-stack) must not exceed a single byte. • Any error in operands (amount and size) must be handled by: • Printing an error • Calculator’s stack must remain unchanged. • The application must never crash! Throw error messages and ignore bad operations when needed.
Assignment #2 • Note that Addition (+) requires adding the least-significant side of operands to easily calculate carry, while • Div (/) requires calculation that starts at the most-significant side of the large operand. • To handle this one can: • Expand the linked-list to a doubly-linked list, or • Use recursion in the Div operation. • The implementation is up to the programmer; These are merely suggestions.