Difference between revisions of "CSC231 Homework 2 2017"
(→Problem #2) |
|||
Line 24: | Line 24: | ||
cp hw2_skel.asm hw2.asm | cp hw2_skel.asm hw2.asm | ||
− | You should now have a new file called hw2.asm in your directory, and | + | You should now have a new file called hw2.asm in your directory, and another file called 231Lib.asm. 231Lib.asm is a library we will use to print and input decimal numbers. The library file will help us get input from the keyboard, and print strings. |
The hw2.asm file is just a skeleton and you will need to add code to it to solve this problem. For right now, just assemble and link it to the new library, and run it: | The hw2.asm file is just a skeleton and you will need to add code to it to solve this problem. For right now, just assemble and link it to the new library, and run it: | ||
Line 55: | Line 55: | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
+ | =Assembly File= | ||
+ | <br /> | ||
+ | Below are the two files used in Problem 2, for reference. | ||
+ | <br /> | ||
+ | ==hw2.asm== | ||
+ | <br /> | ||
+ | ::<source lang="asm"> | ||
+ | ;;; hw2.asm | ||
+ | ;;; put your name here | ||
+ | ;;; describe what the program does | ||
+ | ;;; explain how to assemble and run it. | ||
+ | |||
+ | |||
+ | extern _printDec | ||
+ | extern _printString | ||
+ | extern _println | ||
+ | extern _getInput | ||
+ | |||
+ | section .data | ||
+ | prompt db "> " | ||
+ | promptLen equ $-prompt | ||
+ | ansStr db "ans = " | ||
+ | ansStrLen equ $-ansStr | ||
+ | |||
+ | a dd 0 | ||
+ | b dd 0 | ||
+ | c dd 0 | ||
+ | ans dd 0 | ||
+ | |||
+ | section .text | ||
+ | global _start | ||
+ | _start: | ||
+ | ;; display prompt | ||
+ | mov ecx, prompt | ||
+ | mov edx, promptLen | ||
+ | call _printString | ||
+ | ;; get a | ||
+ | call _getInput | ||
+ | mov dword[a], eax | ||
+ | |||
+ | ;; display prompt | ||
+ | mov ecx, prompt | ||
+ | mov edx, promptLen | ||
+ | call _printString | ||
+ | ;; get b | ||
+ | call _getInput | ||
+ | mov dword[b], eax | ||
+ | |||
+ | ;; display prompt | ||
+ | mov ecx, prompt | ||
+ | mov edx, promptLen | ||
+ | call _printString | ||
+ | ;; get c | ||
+ | call _getInput | ||
+ | mov dword[c], eax | ||
+ | |||
+ | ;; ----------------------------------- | ||
+ | ;; computation: ans = 2*(a-b) + 3*c | ||
+ | ;; ----------------------------------- | ||
+ | |||
+ | ; your code will go here... | ||
+ | |||
+ | |||
+ | ;; ----------------------------------- | ||
+ | ;; display "ans =" | ||
+ | ;; ----------------------------------- | ||
+ | mov ecx, ansStr | ||
+ | mov edx, ansStrLen | ||
+ | call _printString | ||
+ | |||
+ | ;; ----------------------------------- | ||
+ | ;; display ans variable | ||
+ | ;; ----------------------------------- | ||
+ | mov eax, dword[ans] | ||
+ | call _printDec | ||
+ | call _println | ||
+ | call _println | ||
+ | |||
+ | ;;; exit | ||
+ | mov ebx, 0 | ||
+ | mov eax, 1 | ||
+ | int 0x80 | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | ==231Lib.asm== | ||
+ | <br /> | ||
+ | ::<source lang="asm"> | ||
+ | ;;; 231Lib.asm | ||
+ | ;;; A simple I/O library for CSC231. | ||
+ | ;;; will be expanded as needed. | ||
+ | ;;; | ||
+ | ;;; D. Thiebaut | ||
+ | ;;; Adapted from Swarnali Ahmed's 2002 program: mytools.inc | ||
+ | ;;; http://cs.smith.edu/dftwiki | ||
+ | ;;; | ||
+ | ;;; Contains several functions for performing simple I/O of | ||
+ | ;;; data. | ||
+ | ;;; _printDec: function that prints an integer on the screen | ||
+ | ;;; _printString: function that prints a string on the screen | ||
+ | ;;; _println: moves the cursor to the next line on the screen | ||
+ | ;;; _getInput: gets a possibly signed integer from the keyboard | ||
+ | ;;; | ||
+ | ;;; Version 2. Sept 22, 2014. | ||
+ | ;;; - updated _getInput to get only 1 char at at time. | ||
+ | ;;; - now works with pipes | ||
+ | ;;; Version 1. Sept 21, 2014. | ||
+ | ;;; | ||
+ | %assign SYS_EXIT 1 | ||
+ | %assign SYS_WRITE 4 | ||
+ | %assign STDOUT 1 | ||
+ | |||
+ | global _printDec | ||
+ | global _printString | ||
+ | global _println | ||
+ | global _getInput | ||
+ | global _printRegs | ||
+ | global _printHex | ||
+ | |||
+ | |||
+ | |||
+ | section .text | ||
+ | |||
+ | |||
+ | ;;; ;------------------------------------------------------ | ||
+ | ;;; ;------------------------------------------------------ | ||
+ | ;;; ; getInput: gets a numerical input from the keyboard. | ||
+ | ;;; ; returns the resulting number in eax (32 bits). | ||
+ | ;;; ; recognize - as the first character of | ||
+ | ;;; ; negative numbers. Does not skip whitespace | ||
+ | ;;; ; at the beginning. Stops on first not decimal | ||
+ | ;;; ; character encountered. | ||
+ | ;;; ; | ||
+ | ;;; ; NO REGISTERS MODIFIED, except eax | ||
+ | ;;; ; | ||
+ | ;;; ; Example of call: | ||
+ | ;;; ; | ||
+ | ;;; ; call getInput | ||
+ | ;;; ; mov dword[x], eax ; put integer in x | ||
+ | ;;; ; | ||
+ | ;;; ;------------------------------------------------------ | ||
+ | ;;; ;------------------------------------------------------ | ||
+ | _getInput: | ||
+ | section .bss | ||
+ | buffer resb 120 | ||
+ | intg resd 1 | ||
+ | isneg resb 1 | ||
+ | |||
+ | section .text | ||
+ | pushad ; save all registers | ||
+ | |||
+ | mov esi, buffer ; eci --> buffer | ||
+ | mov edi, 0 ; edi = counter of chars | ||
+ | .loop1: | ||
+ | mov eax, 03 ; input | ||
+ | mov ebx, 0 ; stdin | ||
+ | mov ecx, esi ; where to put the next char | ||
+ | mov edx, 1 ; one char at a time | ||
+ | int 0x80 ; get the input into buffer | ||
+ | |||
+ | cmp byte[esi], 0 ; EOF? | ||
+ | je .parse | ||
+ | cmp byte[esi], 10 ; line feed? | ||
+ | je .parse | ||
+ | inc esi ; point to next cell | ||
+ | inc edi ; increment char counter | ||
+ | jmp .loop1 | ||
+ | |||
+ | .parse: | ||
+ | mov esi, buffer ; esi --> buffer | ||
+ | mov ecx, edi ; loop for all chars received | ||
+ | mov dword[intg], 0 | ||
+ | mov byte[isneg], 0 | ||
+ | |||
+ | .negativ: | ||
+ | cmp byte[esi], '-' | ||
+ | jne .loop | ||
+ | inc byte[isneg] | ||
+ | |||
+ | .loop: mov ebx, 0 | ||
+ | mov bl, byte[esi] | ||
+ | |||
+ | ;; stop on line feed | ||
+ | cmp bl, 10 ; line feed? | ||
+ | je .done | ||
+ | |||
+ | ;; stop on non-digit characters | ||
+ | cmp bl, '0' | ||
+ | jb .done | ||
+ | cmp bl, '9' | ||
+ | ja .done | ||
+ | |||
+ | ;; bl is a digit... multiply .int by 10 first | ||
+ | mov edx, 10 | ||
+ | mov eax, dword[intg] | ||
+ | mul edx ; edx:eax <-- 10 * .int | ||
+ | |||
+ | ;; add int version of char | ||
+ | sub bl, '0' | ||
+ | add eax, ebx | ||
+ | mov dword[intg], eax | ||
+ | inc esi | ||
+ | loop .loop | ||
+ | .done: | ||
+ | ;; if negative, make eax neg | ||
+ | cmp byte[isneg], 0 | ||
+ | je .return | ||
+ | neg eax | ||
+ | mov dword [intg], eax | ||
+ | |||
+ | ;; restore registers and return result in eax | ||
+ | .return: | ||
+ | |||
+ | popad | ||
+ | mov eax, [intg] | ||
+ | ret | ||
+ | |||
+ | |||
+ | ;;; ;------------------------------------------------------ | ||
+ | ;;; ;------------------------------------------------------ | ||
+ | ;;; ; _printDec: takes the double word in eax and prints it | ||
+ | ;;; ; to STDOUT in decimal. | ||
+ | ;;; ; | ||
+ | ;;; ; Examples: | ||
+ | ;;; ; print a byte variable | ||
+ | ;;; ; mov eax, 0 | ||
+ | ;;; ; mov al, byte[someVar] | ||
+ | ;;; ; call _printDec | ||
+ | ;;; ; | ||
+ | ;;; ; print a word variable | ||
+ | ;;; ; mov eax | ||
+ | ;;; ; mov ax, word[otherVar] | ||
+ | ;;; ; call _printDec | ||
+ | ;;; ; | ||
+ | ;;; ; print a double-word variable | ||
+ | ;;; ; mov eax, dword[thirdVar] | ||
+ | ;;; ; call _printDec | ||
+ | ;;; ; | ||
+ | ;;; ; print register edx in decimal | ||
+ | ;;; ; | ||
+ | ;;; ; mov eax, edx | ||
+ | ;;; ; call _printDec | ||
+ | ;;; ; | ||
+ | ;;; ;REGISTERS MODIFIED: NONE | ||
+ | ;;; ;------------------------------------------------------ | ||
+ | ;;; ;------------------------------------------------------ | ||
+ | |||
+ | _printDec: | ||
+ | ;;; saves all the registers so that they are not changed by the function | ||
+ | |||
+ | section .bss | ||
+ | .decstr resb 10 | ||
+ | .ct1 resd 1 ; to keep track of the size of the string | ||
+ | |||
+ | section .text | ||
+ | pushad ; save all registers | ||
+ | |||
+ | mov dword[.ct1],0 ; assume initially 0 | ||
+ | mov edi,.decstr ; edi points to decstring | ||
+ | add edi,9 ; moved to the last element of string | ||
+ | xor edx,edx ; clear edx for 64-bit division | ||
+ | .whileNotZero: | ||
+ | mov ebx,10 ; get ready to divide by 10 | ||
+ | div ebx ; divide by 10 | ||
+ | add edx,'0' ; converts to ascii char | ||
+ | mov byte[edi],dl ; put it in sring | ||
+ | dec edi ; mov to next char in string | ||
+ | inc dword[.ct1] ; increment char counter | ||
+ | xor edx,edx ; clear edx | ||
+ | cmp eax,0 ; is remainder of division 0? | ||
+ | jne .whileNotZero ; no, keep on looping | ||
+ | |||
+ | inc edi ; conversion, finish, bring edi | ||
+ | mov ecx, edi ; back to beg of string. make ecx | ||
+ | mov edx, [.ct1] ; point to it, and edx gets # chars | ||
+ | mov eax, SYS_WRITE ; and print! | ||
+ | mov ebx, STDOUT | ||
+ | int 0x80 | ||
+ | |||
+ | popad ; restore all registers | ||
+ | |||
+ | ret | ||
+ | |||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | ;;; ; _printString: prints a string whose address is in | ||
+ | ;;; ; ecx, and whose total number of chars | ||
+ | ;;; ; is in edx. | ||
+ | ;;; ; Examples: | ||
+ | ;;; ; Assume a string labeled msg, containing "Hello World!", | ||
+ | ;;; ; and a constant MSGLEN equal to 12. To print this string: | ||
+ | ;;; ; | ||
+ | ;;; ; mov ecx, msg | ||
+ | ;;; ; mov edx, MSGLEN | ||
+ | ;;; ; call _printSTring | ||
+ | ;;; ; | ||
+ | ;;; ; REGISTERS MODIFIED: NONE | ||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | |||
+ | ;;; ;save eax and ebx so that it is not modified by the function | ||
+ | |||
+ | _printString: | ||
+ | push eax | ||
+ | push ebx | ||
+ | |||
+ | mov eax,SYS_WRITE | ||
+ | mov ebx,STDOUT | ||
+ | int 0x80 | ||
+ | |||
+ | pop ebx | ||
+ | pop eax | ||
+ | ret | ||
+ | |||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | ;;; ; _println put the cursor on the next line. | ||
+ | ;;; ; | ||
+ | ;;; ; Example: | ||
+ | ;;; ; call _println | ||
+ | ;;; ; | ||
+ | ;;; ; REGISTERS MODIFIED: NONE | ||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | _println: | ||
+ | section .data | ||
+ | .nl db 10 | ||
+ | |||
+ | section .text | ||
+ | push ecx | ||
+ | push edx | ||
+ | |||
+ | mov ecx, .nl | ||
+ | mov edx, 1 | ||
+ | call _printString | ||
+ | |||
+ | pop edx | ||
+ | pop ecx | ||
+ | ret | ||
+ | |||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | ;;; ; _printHex: prints contents of eax in hexadecimal, uppercase. | ||
+ | ;;; ; using 8 chars. | ||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | section .data | ||
+ | table db "0123456789ABCDEF" | ||
+ | hexString db "xxxxxxxx" | ||
+ | tempEax dd 0 | ||
+ | |||
+ | section .text | ||
+ | _printHex: | ||
+ | pushad ; save all registers | ||
+ | mov [tempEax], eax ; save eax, as we are going to need it | ||
+ | ; several times, for all its digits | ||
+ | mov ecx, 8 ; get ready to loop 8 times | ||
+ | |||
+ | ;; get char equivalent to lower nybble of eax | ||
+ | for: and eax, 0xF ; isolate lower nybble of eax | ||
+ | add eax, table ; and translate it into ascii hex char | ||
+ | mov bl, byte[eax] ; bl <- ascii | ||
+ | |||
+ | ;; make eax point to place where to put this digit in hexString | ||
+ | mov eax, hexString ; beginning of table | ||
+ | add eax, ecx ; add ecx to it, since ecx counts | ||
+ | dec eax ; but eax 1 too big, decrement it | ||
+ | mov byte[eax], bl ; store ascii char at right index in hexString | ||
+ | |||
+ | ;; shift eax down by 4 bits by dividing it by 16 | ||
+ | mov ebx, 16 ; ready to shift down by 4 bits | ||
+ | mov eax, [tempEax] ; get eax back | ||
+ | div ebx ; shift down by 4 | ||
+ | mov [tempEax], eax ; save again | ||
+ | |||
+ | loop for ; and repeat, 8 times! | ||
+ | |||
+ | ;; print the pattern in hexString, which contains 8 chars | ||
+ | |||
+ | mov ecx, hexString ; | ||
+ | mov edx, 8 | ||
+ | call _printString | ||
+ | |||
+ | popad | ||
+ | ret | ||
+ | |||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | ;;; ; _printInt: prints the contents of eax as a 2's complement | ||
+ | ;;; ; number. | ||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | _printInt: push eax ; save the regs we are using | ||
+ | push ecx | ||
+ | push edx | ||
+ | |||
+ | ;; check if msb is set | ||
+ | cmp eax, 0x8000000 | ||
+ | jb positive | ||
+ | push eax | ||
+ | |||
+ | ;; the number is negative. Print a minus sign and | ||
+ | ;; the positive equivalent of the number | ||
+ | mov ecx, minus | ||
+ | mov edx, 1 | ||
+ | call _printString | ||
+ | pop eax | ||
+ | neg eax | ||
+ | |||
+ | ;; the number is positive, just print it. | ||
+ | positive: call _printDec | ||
+ | |||
+ | pop edx | ||
+ | pop ecx | ||
+ | pop eax | ||
+ | ret | ||
+ | |||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | ;;; ; printMinus, _printSpace: print a minus sign, and a plus sign. | ||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | _printMinus: push ecx | ||
+ | push edx | ||
+ | mov ecx, minus | ||
+ | mov edx, 1 | ||
+ | call _printString | ||
+ | pop edx | ||
+ | pop ecx | ||
+ | ret | ||
+ | |||
+ | _printSpace: push ecx | ||
+ | push edx | ||
+ | mov ecx, space | ||
+ | mov edx, 1 | ||
+ | call _printString | ||
+ | pop edx | ||
+ | pop ecx | ||
+ | ret | ||
+ | |||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | ;;; ; _printRegs: prints all the registers. | ||
+ | ;;; ; ------------------------------------------------------------ | ||
+ | section .data | ||
+ | minus db '-' | ||
+ | space db ' ' | ||
+ | eaxStr db 'eax ' | ||
+ | ebxStr db 'ebx ' | ||
+ | ecxStr db 'ecx ' | ||
+ | edxStr db 'edx ' | ||
+ | esiStr db 'esi ' | ||
+ | ediStr db 'edi ' | ||
+ | eaxTemp dd 0 | ||
+ | ebxTemp dd 0 | ||
+ | ecxTemp dd 0 | ||
+ | edxTemp dd 0 | ||
+ | esiTemp dd 0 | ||
+ | ediTemp dd 0 | ||
+ | |||
+ | section .text | ||
+ | _printRegs: mov [eaxTemp], eax | ||
+ | mov [ebxTemp], ebx | ||
+ | mov [ecxTemp], ecx | ||
+ | mov [edxTemp], edx | ||
+ | mov [ediTemp], edi | ||
+ | mov [esiTemp], esi | ||
+ | |||
+ | pushad | ||
+ | |||
+ | ;; print eax | ||
+ | mov ecx, eaxStr | ||
+ | mov edx, 4 | ||
+ | call _printString | ||
+ | call _printHex | ||
+ | call _printSpace | ||
+ | call _printDec | ||
+ | call _printSpace | ||
+ | call _printInt | ||
+ | call _println | ||
+ | |||
+ | ;; print ebx | ||
+ | mov ecx, ebxStr | ||
+ | mov edx, 4 | ||
+ | call _printString | ||
+ | mov eax, [ebxTemp] | ||
+ | call _printHex | ||
+ | call _printSpace | ||
+ | call _printDec | ||
+ | call _printSpace | ||
+ | call _printInt | ||
+ | call _println | ||
+ | |||
+ | ;; print ecx | ||
+ | mov ecx, ecxStr | ||
+ | mov edx, 4 | ||
+ | call _printString | ||
+ | mov eax, [ecxTemp] | ||
+ | call _printHex | ||
+ | call _printSpace | ||
+ | call _printDec | ||
+ | call _printSpace | ||
+ | call _printInt | ||
+ | call _println | ||
+ | |||
+ | ;; print edx | ||
+ | mov ecx, edxStr | ||
+ | mov edx, 4 | ||
+ | call _printString | ||
+ | mov eax, [edxTemp] | ||
+ | call _printHex | ||
+ | call _printSpace | ||
+ | call _printDec | ||
+ | call _printSpace | ||
+ | call _printInt | ||
+ | call _println | ||
+ | |||
+ | ;; print edi | ||
+ | mov ecx, ediStr | ||
+ | mov edx, 4 | ||
+ | call _printString | ||
+ | mov eax, [ediTemp] | ||
+ | call _printHex | ||
+ | call _printSpace | ||
+ | call _printDec | ||
+ | call _printSpace | ||
+ | call _printInt | ||
+ | call _println | ||
+ | |||
+ | ;; print esi | ||
+ | mov ecx, esiStr | ||
+ | mov edx, 4 | ||
+ | call _printString | ||
+ | mov eax, [esiTemp] | ||
+ | call _printHex | ||
+ | call _printSpace | ||
+ | call _printDec | ||
+ | call _printSpace | ||
+ | call _printInt | ||
+ | call _println | ||
+ | |||
+ | popad | ||
+ | |||
+ | ret | ||
+ | |||
+ | </source> | ||
<br /> | <br /> | ||
[[Category:CSC231]][[Category:Homework]] | [[Category:CSC231]][[Category:Homework]] |
Revision as of 16:20, 9 February 2017
--D. Thiebaut (talk) 16:14, 9 February 2017 (EST)
This assignment is due on 2/20/17 at 11:55 p.m.
Problem #1
Answer the quizzes in the Moodle Homework 2 section.
Problem #2
In your 231b-xx account on aurora, run the following commands:
getcopy 231Lib.asm getcopy hw2_skel.asm cp hw2_skel.asm hw2.asm
You should now have a new file called hw2.asm in your directory, and another file called 231Lib.asm. 231Lib.asm is a library we will use to print and input decimal numbers. The library file will help us get input from the keyboard, and print strings.
The hw2.asm file is just a skeleton and you will need to add code to it to solve this problem. For right now, just assemble and link it to the new library, and run it:
nasm -f elf 231Lib.asm ld -o hw2 hw2.o 231Lib.o ld -melf_i386 -o hw2 hw2.o 231Lib.o
The program will prompt you for 3 integer numbers, which it will put into three 32-bit integers called a, b, and c in the data segment. It then takes the integer stored in a fourth variable called ans (for answer), and prints it. Since ans is initialized with 0, that's the number that gets printed.
Here's an example of what happens if I run the program and feed it 3 numbers: 1, 2, and 3 (user input underlined):
./hw2 > 1 > 2 > 3 ans = 0
Assembly File
Below are the two files used in Problem 2, for reference.
hw2.asm
;;; hw2.asm ;;; put your name here ;;; describe what the program does ;;; explain how to assemble and run it. extern _printDec extern _printString extern _println extern _getInput section .data prompt db "> " promptLen equ $-prompt ansStr db "ans = " ansStrLen equ $-ansStr a dd 0 b dd 0 c dd 0 ans dd 0 section .text global _start _start: ;; display prompt mov ecx, prompt mov edx, promptLen call _printString ;; get a call _getInput mov dword[a], eax ;; display prompt mov ecx, prompt mov edx, promptLen call _printString ;; get b call _getInput mov dword[b], eax ;; display prompt mov ecx, prompt mov edx, promptLen call _printString ;; get c call _getInput mov dword[c], eax ;; ----------------------------------- ;; computation: ans = 2*(a-b) + 3*c ;; ----------------------------------- ; your code will go here... ;; ----------------------------------- ;; display "ans =" ;; ----------------------------------- mov ecx, ansStr mov edx, ansStrLen call _printString ;; ----------------------------------- ;; display ans variable ;; ----------------------------------- mov eax, dword[ans] call _printDec call _println call _println ;;; exit mov ebx, 0 mov eax, 1 int 0x80
231Lib.asm
;;; 231Lib.asm ;;; A simple I/O library for CSC231. ;;; will be expanded as needed. ;;; ;;; D. Thiebaut ;;; Adapted from Swarnali Ahmed's 2002 program: mytools.inc ;;; http://cs.smith.edu/dftwiki ;;; ;;; Contains several functions for performing simple I/O of ;;; data. ;;; _printDec: function that prints an integer on the screen ;;; _printString: function that prints a string on the screen ;;; _println: moves the cursor to the next line on the screen ;;; _getInput: gets a possibly signed integer from the keyboard ;;; ;;; Version 2. Sept 22, 2014. ;;; - updated _getInput to get only 1 char at at time. ;;; - now works with pipes ;;; Version 1. Sept 21, 2014. ;;; %assign SYS_EXIT 1 %assign SYS_WRITE 4 %assign STDOUT 1 global _printDec global _printString global _println global _getInput global _printRegs global _printHex section .text ;;; ;------------------------------------------------------ ;;; ;------------------------------------------------------ ;;; ; getInput: gets a numerical input from the keyboard. ;;; ; returns the resulting number in eax (32 bits). ;;; ; recognize - as the first character of ;;; ; negative numbers. Does not skip whitespace ;;; ; at the beginning. Stops on first not decimal ;;; ; character encountered. ;;; ; ;;; ; NO REGISTERS MODIFIED, except eax ;;; ; ;;; ; Example of call: ;;; ; ;;; ; call getInput ;;; ; mov dword[x], eax ; put integer in x ;;; ; ;;; ;------------------------------------------------------ ;;; ;------------------------------------------------------ _getInput: section .bss buffer resb 120 intg resd 1 isneg resb 1 section .text pushad ; save all registers mov esi, buffer ; eci --> buffer mov edi, 0 ; edi = counter of chars .loop1: mov eax, 03 ; input mov ebx, 0 ; stdin mov ecx, esi ; where to put the next char mov edx, 1 ; one char at a time int 0x80 ; get the input into buffer cmp byte[esi], 0 ; EOF? je .parse cmp byte[esi], 10 ; line feed? je .parse inc esi ; point to next cell inc edi ; increment char counter jmp .loop1 .parse: mov esi, buffer ; esi --> buffer mov ecx, edi ; loop for all chars received mov dword[intg], 0 mov byte[isneg], 0 .negativ: cmp byte[esi], '-' jne .loop inc byte[isneg] .loop: mov ebx, 0 mov bl, byte[esi] ;; stop on line feed cmp bl, 10 ; line feed? je .done ;; stop on non-digit characters cmp bl, '0' jb .done cmp bl, '9' ja .done ;; bl is a digit... multiply .int by 10 first mov edx, 10 mov eax, dword[intg] mul edx ; edx:eax <-- 10 * .int ;; add int version of char sub bl, '0' add eax, ebx mov dword[intg], eax inc esi loop .loop .done: ;; if negative, make eax neg cmp byte[isneg], 0 je .return neg eax mov dword [intg], eax ;; restore registers and return result in eax .return: popad mov eax, [intg] ret ;;; ;------------------------------------------------------ ;;; ;------------------------------------------------------ ;;; ; _printDec: takes the double word in eax and prints it ;;; ; to STDOUT in decimal. ;;; ; ;;; ; Examples: ;;; ; print a byte variable ;;; ; mov eax, 0 ;;; ; mov al, byte[someVar] ;;; ; call _printDec ;;; ; ;;; ; print a word variable ;;; ; mov eax ;;; ; mov ax, word[otherVar] ;;; ; call _printDec ;;; ; ;;; ; print a double-word variable ;;; ; mov eax, dword[thirdVar] ;;; ; call _printDec ;;; ; ;;; ; print register edx in decimal ;;; ; ;;; ; mov eax, edx ;;; ; call _printDec ;;; ; ;;; ;REGISTERS MODIFIED: NONE ;;; ;------------------------------------------------------ ;;; ;------------------------------------------------------ _printDec: ;;; saves all the registers so that they are not changed by the function section .bss .decstr resb 10 .ct1 resd 1 ; to keep track of the size of the string section .text pushad ; save all registers mov dword[.ct1],0 ; assume initially 0 mov edi,.decstr ; edi points to decstring add edi,9 ; moved to the last element of string xor edx,edx ; clear edx for 64-bit division .whileNotZero: mov ebx,10 ; get ready to divide by 10 div ebx ; divide by 10 add edx,'0' ; converts to ascii char mov byte[edi],dl ; put it in sring dec edi ; mov to next char in string inc dword[.ct1] ; increment char counter xor edx,edx ; clear edx cmp eax,0 ; is remainder of division 0? jne .whileNotZero ; no, keep on looping inc edi ; conversion, finish, bring edi mov ecx, edi ; back to beg of string. make ecx mov edx, [.ct1] ; point to it, and edx gets # chars mov eax, SYS_WRITE ; and print! mov ebx, STDOUT int 0x80 popad ; restore all registers ret ;;; ; ------------------------------------------------------------ ;;; ; _printString: prints a string whose address is in ;;; ; ecx, and whose total number of chars ;;; ; is in edx. ;;; ; Examples: ;;; ; Assume a string labeled msg, containing "Hello World!", ;;; ; and a constant MSGLEN equal to 12. To print this string: ;;; ; ;;; ; mov ecx, msg ;;; ; mov edx, MSGLEN ;;; ; call _printSTring ;;; ; ;;; ; REGISTERS MODIFIED: NONE ;;; ; ------------------------------------------------------------ ;;; ;save eax and ebx so that it is not modified by the function _printString: push eax push ebx mov eax,SYS_WRITE mov ebx,STDOUT int 0x80 pop ebx pop eax ret ;;; ; ------------------------------------------------------------ ;;; ; _println put the cursor on the next line. ;;; ; ;;; ; Example: ;;; ; call _println ;;; ; ;;; ; REGISTERS MODIFIED: NONE ;;; ; ------------------------------------------------------------ _println: section .data .nl db 10 section .text push ecx push edx mov ecx, .nl mov edx, 1 call _printString pop edx pop ecx ret ;;; ; ------------------------------------------------------------ ;;; ; _printHex: prints contents of eax in hexadecimal, uppercase. ;;; ; using 8 chars. ;;; ; ------------------------------------------------------------ section .data table db "0123456789ABCDEF" hexString db "xxxxxxxx" tempEax dd 0 section .text _printHex: pushad ; save all registers mov [tempEax], eax ; save eax, as we are going to need it ; several times, for all its digits mov ecx, 8 ; get ready to loop 8 times ;; get char equivalent to lower nybble of eax for: and eax, 0xF ; isolate lower nybble of eax add eax, table ; and translate it into ascii hex char mov bl, byte[eax] ; bl <- ascii ;; make eax point to place where to put this digit in hexString mov eax, hexString ; beginning of table add eax, ecx ; add ecx to it, since ecx counts dec eax ; but eax 1 too big, decrement it mov byte[eax], bl ; store ascii char at right index in hexString ;; shift eax down by 4 bits by dividing it by 16 mov ebx, 16 ; ready to shift down by 4 bits mov eax, [tempEax] ; get eax back div ebx ; shift down by 4 mov [tempEax], eax ; save again loop for ; and repeat, 8 times! ;; print the pattern in hexString, which contains 8 chars mov ecx, hexString ; mov edx, 8 call _printString popad ret ;;; ; ------------------------------------------------------------ ;;; ; _printInt: prints the contents of eax as a 2's complement ;;; ; number. ;;; ; ------------------------------------------------------------ _printInt: push eax ; save the regs we are using push ecx push edx ;; check if msb is set cmp eax, 0x8000000 jb positive push eax ;; the number is negative. Print a minus sign and ;; the positive equivalent of the number mov ecx, minus mov edx, 1 call _printString pop eax neg eax ;; the number is positive, just print it. positive: call _printDec pop edx pop ecx pop eax ret ;;; ; ------------------------------------------------------------ ;;; ; printMinus, _printSpace: print a minus sign, and a plus sign. ;;; ; ------------------------------------------------------------ _printMinus: push ecx push edx mov ecx, minus mov edx, 1 call _printString pop edx pop ecx ret _printSpace: push ecx push edx mov ecx, space mov edx, 1 call _printString pop edx pop ecx ret ;;; ; ------------------------------------------------------------ ;;; ; _printRegs: prints all the registers. ;;; ; ------------------------------------------------------------ section .data minus db '-' space db ' ' eaxStr db 'eax ' ebxStr db 'ebx ' ecxStr db 'ecx ' edxStr db 'edx ' esiStr db 'esi ' ediStr db 'edi ' eaxTemp dd 0 ebxTemp dd 0 ecxTemp dd 0 edxTemp dd 0 esiTemp dd 0 ediTemp dd 0 section .text _printRegs: mov [eaxTemp], eax mov [ebxTemp], ebx mov [ecxTemp], ecx mov [edxTemp], edx mov [ediTemp], edi mov [esiTemp], esi pushad ;; print eax mov ecx, eaxStr mov edx, 4 call _printString call _printHex call _printSpace call _printDec call _printSpace call _printInt call _println ;; print ebx mov ecx, ebxStr mov edx, 4 call _printString mov eax, [ebxTemp] call _printHex call _printSpace call _printDec call _printSpace call _printInt call _println ;; print ecx mov ecx, ecxStr mov edx, 4 call _printString mov eax, [ecxTemp] call _printHex call _printSpace call _printDec call _printSpace call _printInt call _println ;; print edx mov ecx, edxStr mov edx, 4 call _printString mov eax, [edxTemp] call _printHex call _printSpace call _printDec call _printSpace call _printInt call _println ;; print edi mov ecx, ediStr mov edx, 4 call _printString mov eax, [ediTemp] call _printHex call _printSpace call _printDec call _printSpace call _printInt call _println ;; print esi mov ecx, esiStr mov edx, 4 call _printString mov eax, [esiTemp] call _printHex call _printSpace call _printDec call _printSpace call _printInt call _println popad ret