NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: RaenirS on March 26, 2013, 04:31:02 AM
-
Below is my code based on some code snippets I found online that I tried to cudgle together. The result of 1234 into the 2 v 2 matrix is for the largest number to be 3, while the result of 4321 is accurately 4; with some weirdness if I use other numbers.
Seems like to me that its only finding the largest number of the first row, and not the other rows.
Also the anti spam picture game is kinda obnixious the first 50 times... Does it ever go away?
segment .bss
num: resw 1 ;For storing a number, to be read of printed....
nod: resb 1 ;For storing the number of digits....
temp: resb 2
matrix1: resw 200
m: resw 1
n: resw 1
i: resw 1
j: resw 1
buff resb 4
segment .data
msg1: db "Enter the number of rows in the matrix : "
msg_size1: equ $-msg1
msg2: db "Enter the elements one by one(row by row) : "
msg_size2: equ $-msg2
msg3: db "Enter the number of columns in the matrix : "
msg_size3: equ $-msg3
tab: db 9 ;ASCII for vertical tab
new_line: db 10 ;ASCII for new line
segment .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, msg_size1
int 80h
mov ecx, 0
call read_num
mov cx, word[num]
mov word[m], cx
mov eax, 4
mov ebx, 1
mov ecx, msg3
mov edx, msg_size3
int 80h
mov ecx, 0
call read_num
mov cx, word[num]
mov word[n], cx
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, msg_size2
int 80h
;Reading each element of the matrix........
mov eax, 0
mov ebx, matrix1
mov word[i], 0
mov word[j], 0
i_loop:
mov word[j], 0
j_loop:
call read_num
mov dx , word[num]
;eax will contain the array index and each element is 2 bytes(1 word) long
mov word[ebx + 2 * eax], dx
inc eax ;Incrementing array index by one....
inc word[j]
mov cx, word[j]
cmp cx, word[n]
jb j_loop
inc word[i]
mov cx, word[i]
cmp cx, word[m]
jb i_loop
; read out matrix code
xor esp, [matrix1] ; esp initialized to first element in array, & is first largest value
;xor edi, edi ; edi initialized to 0, edi is loop counter
;Pretty sure this is the "read" matrix code.
;Reading each element of the matrix.(Storing the elements in row major order).......
mov ebp, 0
mov edi, matrix1
mov word[i], 0
mov word[j], 0
i_loop2:
mov word[j], 0
j_loop2:
;eax will contain the array index and each element is 2 bytes(1 word) long
mov dx, word[edi+2*ebp] ;
mov word[num] , dx
;call print_num ; stub
;cmp esp, [edi+2*ebp] ;word[ebx + 2 * eax] ; compares current biggest number with current element iterated.
;;;; #### I think this is my debug mode code.... ;;;;
mov eax, 4 ;
mov ebx, 1
mov ecx, [edi+2*ebp]
add ecx, 48
mov [buff], ecx
mov ecx, buff
mov edx, 4
int 80h
cmp esp, [edi+2*ebp] ;word[ebx + 2 * eax] ; compares current biggest number with current element iterated.
jge skip
mov esp, [edi+2*ebp] ;word[ebx + 2 * eax] ; stores new biggest number
mov esi, ebp ; Stores pointer to the biggest element
skip:
inc ebp
inc word[j]
mov cx, word[j]
cmp cx, word[n]
jb j_loop2
inc word[i]
mov cx, word[i]
cmp cx, word[m]
jb i_loop2
;;matrix hack exit code ... //
;loop:
;cmp edi, 25 ; Make sure the end of the matrix has not been reached // set to 25
;jge end_loop ; If the end has been reached, jump out of the loop
; If it's not greater than the current max, skip it
; mov eax, 4 ;
; mov ebx, 1
; mov ecx, [matrix+edi*4]
; add ecx, 48
; mov [buff], ecx
; mov ecx, buff
; mov edx, 4
; int 80h
;add edi, 1 ; increment the counter
;jmp loop ; Loop to the end of the matrix
;end_loop:
; outut
mov eax, 4 ; system_write
mov ebx, 1 ; stdout
mov ecx, [edi+2*esi] ; move biggest element to accumulator
add ecx, 30h ; convert to ascii representation
mov [buff], ecx ; move to memory
mov ecx, buff ; put pointer in ecx for printing
mov edx, 4 ; size, 4 bytes
int 80h ; sytem call.
exit:
mov eax, 1
mov ebx, 0
int 80h
;Function to read a number from console and to store that in num
read_num:
pusha
mov word[num], 0
loop_read:
mov eax, 3
mov ebx, 0
mov ecx, temp
mov edx, 1
int 80h
cmp byte[temp], 10
je end_read
mov ax, word[num]
mov bx, 10
mul bx
mov bl, byte[temp]
sub bl, 30h
mov bh, 0
add ax, bx
mov word[num], ax
jmp loop_read
end_read:
popa
ret
-
I get really confused around here...
; read out matrix code
xor esp, [matrix1] ; esp initialized to first element in array, & is first largest value
In the first place, esp is your stack pointer and it's generally not a good idea to put a random value in it. In the second place, it's too big a register - you made the numbers words, remember? Using a 32-bit register is going to get (and compare) two of them. Moving a 32-bit register into your matrix is worse. In the third place, "xor"? Doesn't match what you say in the comment...
You seem to be on the right track. I think if you clear up a few instances of 16/32-bit confusion you'll have it. (it might be easier to use dwords throughout, but your "read_num" is for words...)
I apologize for the guess-the-picture games. I think it goes away after a while. Blame the spammers.
Best,
Frank
-
ESP is the stack pointer as in what it is officially supposed to do/intended? I was running out of registers so I didn't really have a choice. The thing about 16/32 bit has a bit of a problem of where its really difficult to actually output what they contain, the output code template seems to only work with 32 bit registers and the conversion I didn't know what to do, and seemed to largely work; so I didn't want to mess with what wasn't broke.
XOR as I understand it, is an exclusive or that will set the value to a something, if its xor ecx, ecx it "zeroes" out the register the same way as mov ecx, 0 I believe; and does seem to work to point to the first element in the matrix....
I managed to "solve" the problem after a while from switch from the logic which was using the counter pointer of trying to track WHERE the largest number was, to simply storing the largest number as the user inputs it; because the logic seemed to be stuck to the first row and I couldn't get it to unstuck it.
segment .bss
num: resw 1 ;For storing a number, to be read of printed....
nod: resb 1 ;For storing the number of digits....
temp: resb 2
matrix1: resw 200
m: resw 1
n: resw 1
i: resw 1
j: resw 1
buff resb 4
segment .data
msg1: db "Enter the number of rows in the matrix : "
msg_size1: equ $-msg1
msg2: db "Enter the elements one by one(row by row) : "
msg_size2: equ $-msg2
msg3: db "Enter the number of columns in the matrix : "
msg_size3: equ $-msg3
msg4: db "The Largest Number is... : "
msg_size4: equ $-msg4
tab: db 9 ;ASCII for vertical tab
new_line: db 10 ;ASCII for new line
segment .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, msg_size1
int 80h
mov ecx, 0
call read_num
mov cx, word[num]
mov word[m], cx
mov eax, 4
mov ebx, 1
mov ecx, msg3
mov edx, msg_size3
int 80h
mov ecx, 0
call read_num
mov cx, word[num]
mov word[n], cx
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, msg_size2
int 80h
;Reading each element of the matrix........
mov eax, 0
mov ebx, matrix1
mov word[i], 0
mov word[j], 0
i_loop:
mov word[j], 0
j_loop:
call read_num
mov dx , word[num]
;eax will contain the array index and each element is 2 bytes(1 word) long
mov word[ebx + 2 * eax], dx
inc eax ;Incrementing array index by one....
inc word[j]
mov cx, word[j]
cmp cx, word[n]
jb j_loop
inc word[i]
mov cx, word[i]
cmp cx, word[m]
jb i_loop
; read out matrix code
xor esp, [matrix1] ; esp initialized to first element in array, & is first largest value
;xor edi, edi ; edi initialized to 0, edi is loop counter
;Loop through the matrix, check each number if its larger than the first number in the array. AT the end print said number.
;Reading each element of the matrix.(Storing the elements in row major order).......
mov ebp, 0
mov edi, matrix1
mov esp, 0
mov word[i], 0
mov word[j], 0
i_loop2:
mov word[j], 0
j_loop2:
;eax will contain the array index and each element is 2 bytes(1 word) long
mov dx, word[edi+2*ebp] ;
mov word[num] , dx
cmp esp, [num] ;word[ebx + 2 * eax] ; compares current biggest number with current element iterated.
jge skip
mov esp, [num] ;word[ebx + 2 * eax] ; stores new biggest number
mov esi, ebp ; Stores pointer to the biggest element
skip:
;debug code
;mov eax, 4 ;
;mov ebx, 1
;mov ecx, esp
;add ecx, 48
;mov [buff], ecx
;mov ecx, buff
;mov edx, 4
;int 80h
;mov esp, [num]
inc ebp
inc word[j]
mov cx, word[j]
cmp cx, word[n]
jb j_loop2
inc word[i]
mov cx, word[i]
cmp cx, word[m]
jb i_loop2
;outut
mov eax, 4
mov ebx, 1
mov ecx, msg4
mov edx, msg_size4
int 80h
mov ecx, 0
mov eax, 4 ; system_write
mov ebx, 1 ; stdout
mov ecx, esp ; move biggest element to accumulator
add ecx, 48 ; convert to ascii representation
mov [buff], ecx ; move to memory
mov ecx, buff
mov edx, 4 ; size, 4 bytes
int 80h
exit:
mov eax, 1
mov ebx, 0
int 80h
;Function to read a number from console and to store that in num
read_num:
pusha
mov word[num], 0
loop_read:
mov eax, 3
mov ebx, 0
mov ecx, temp
mov edx, 1
int 80h
cmp byte[temp], 10
je end_read
mov ax, word[num]
mov bx, 10
mul bx
mov bl, byte[temp]
sub bl, 30h
mov bh, 0
add ax, bx
mov word[num], ax
jmp loop_read
end_read:
popa
ret
Here's the working code. Ideally I would want it to output based on the position of counter but that only seems to work with a 1 dimensional array, I have no idea how to specify a location in a 2 dimensional array in nasm land.
-
I looked at it again considering my new information and here is what I cannot understand:
the "outer" loop is controlled by cx, which increments by 1.
dx is the value carried at matrix @ position eax (controlled in the inner loop, surprisingly not by ax or whatever the inner loop counter is...?)
SOMEHOW word[edi+2*ebp] (or word[ebx+2*eax] ) KNOWS which row it is at based on cx, how is beyond me as they are never directly refernece afaik, I am likely missing something.
Meaning, if I knew how they were related, then I would need two things, to save the value of "eax/ebp" whichever counter I used for the column index counter, AND the value of the row counter (cx) and then somehow manage to trick through vile magick of which mankind is not meant to know to spit out the number at that location.
Would I, assuming this use:
; outut
mov eax, 4 ; system_write
mov ebx, 1 ; stdout
mov dh, cx ; move row index
mov ecx, [edi+2*esi] ; move biggest element to accumulator
; since esi is the reference to WHERE which column on a given row the biggest number is, assuming
; moving cx "triggers" it to look there, will this be position matrix[dh][esi]?
add ecx, 30h ; convert to ascii representation
mov [buff], ecx ; move to memory
mov ecx, buff ; put pointer in ecx for printing
mov edx, 4 ; size, 4 bytes
int 80h ; sytem call.
-
ESP is the stack pointer as in what it is officially supposed to do/intended? I was running out of registers so I didn't really have a choice.
When your background is a higher level language such as C, C++ or Basic even, you are shielded from the intricacies of the processor. Code and logic therefore are more abstract in nature than coding at this level (assembly). When you understand the intent and purpose of each of the registers, you will soon see how your logic using ESP is flawed. As a matter of fact, that is that pointers intent and purpose to extend temporarily the amount of registers you have if you will.
Even in 64 bit now, I still have to remind myself that there are 8 more I can use (R15-R08).
Ideally I would want it to output based on the position of counter but that only seems to work with a 1 dimensional array, I have no idea how to specify a location in a 2 dimensional array in nasm land.
At this level, there is no such thing as an array. Consider this snippet.
; read_num procedure returns integer value in EAX
call read_num ; Get number of rows, multiplyer
mov ecx, eax
call read_num ; Get number of columns, multiplicand
xor edx, edx ; Needs to be null
imul ecx
shl eax, 1 ; EAX *= 2 (words)
sub esp, eax ; Make room on stack for array
mov ebp, esp ; EBP becomes pointer to that array
push ecx ; Save number of rows @ [EBP-4]
All the app cares about is how much memory, therefore let's consider 9 rows and 24 columns / row. This gives us 216 elements and because we're saving 16 bit values, we need 432 bytes of memory. Then after the stack pointer is adjusted to the appropriate amount of space, the number of rows are saved and is now pointed to by [EBP-4] in this example.
Whenever you want to know what row and column your in, it's simply (CUR_POINTER - BASE_POINTER) / ROWS. Result EAX=Row & EDX=Column
mov ecx, [ebp-4]
mov eax, Pointer
sub eax, ebp
div ecx
The essential points I'd like to make here is, first and foremost, get a really good understanding of the instruction set and architecture. Without those two, you're going to struggle unnecessarily at this level. Secondly, format you code with ample comments with entry points tabulated as a lot of code can be written in a short time and it is easy to lose track of where you are. This is just a small snippet from a boot-loader of mine
; Move postamble out of way as it will probably get overwritten for metrics
; that have max sectors of 63
.MovBlk mov si, A20
call ShowS
mov cx, Block_Size
shr cx, 2 ; Number of words we'll be moving
push cx
shr cx, 2 ; CX = # of 16 byte segments
mov ax, KERNEL_SEG ; Where sectors 2 - n are going to be loaded
sub ax, cx ; Leave room for kernel loader
mov es, ax
xor di, di
mov cx, .Load ; Source buffer
shr cx, 4 ; Determine its segment
mov ax, cs
add ax, cx
mov ds, ax
xor si, si
pop cx
rep movsd
; Because code can change, I wanted to make this algo dynamic, thus the RETF.
mov ax, es ; Build far pointer
push ax
push 0
retf ; Jump to it
align 16 ; So subsequent is aligned on segment boundry
; Determine metrics of media we've booted from
.Load sub sp, PACKET_SIZE ; Space for disk parameters
mov ax, ss
mov ds, ax
mov si, sp ; DS:SI = Pointer to parameters
mov ah, Get_D_Params
mov dx, [bp - 2] ; Get drive # again
int DISK_IO
jc .Err
; Load in remaining sectors of this track/head
mov ax, KERNEL_SEG
mov es, ax
xor bx, bx ; ES:BX = Pointer to desintation buffer
mov cx, 2
mov al, [si + 12]
dec al
mov ah, READ_SECT
int DISK_IO
jc .Err
add sp, PACKET_SIZE ; Recover space used for metrics
jmp KERNEL_SEG:0
; If we get to here, then our loader failed somewhere
.Err mov ax, VIDEO_SEG ; Point to last line of page 0
mov es, ax
mov di, 12
mov cx, 4
mov ax, 0xe4fe
rep stosw
xor ax, ax ; Wait for operator input
int KEYBOARD
int 0x19 ; Re-boot
Block_Size equ $ - .Load