### Author Topic: how to compare between two value stored in the register and get the bigger one?  (Read 30052 times)

#### new_geek

• Jr. Member
• Posts: 11
• Country:
##### how to compare between two value stored in the register and get the bigger one?
« on: October 26, 2013, 04:09:07 AM »
Hi everyone, I am a student of computer science. and I'm taking computer organization and embedded systems. and through googling I got partial code, from that I know how to compare the value between two register (jg, jl, je). But the thing that I want to know, is there a specific code so that we know which value is bigger without having to execute jump (loop)?

P.S: let's say, there is a case we need to compare four or five different value and store the biggest among them in R0 and the smallest in R1.

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2667
• Country:
##### Re: how to compare between two value stored in the register and get the bigger one?
« Reply #1 on: October 26, 2013, 05:40:41 PM »
As a general rule, I think you'll find that assembly language involves writing a large number of simple instructions to do anything. If you've got several values, you're going to have to compare them one at a time to find the largest/smallest. If you've got a more specific question, maybe we can help you with it...

Best,
Frank

#### new_geek

• Jr. Member
• Posts: 11
• Country:
##### Re: how to compare between two value stored in the register and get the bigger one?
« Reply #2 on: October 27, 2013, 11:16:25 PM »
honestly, its part of school project. so in that project we were given four variables, and we supposed to compare each and every one of them. and then we must store the result in ax and dx. the first register is the largest while the other is the smallest.
Quote
Code: [Select]
`section .dataVAR1: dw 30000VAR2: dw 0ABCDHVAR3: dw 7FFFHVAR4: dw 100010001000B section .bsssection .text global _start_start: nop ; TODO: your code here mov ax,0 mov ax, [VAR1] mov bx,0 mov bx, [VAR2] mov dx,0 mov dx, [VAR1];VAR1 dw 30000;VAR2 dw 0ABCDH;VAR3 dw 7FFFH;VAR4 dw 100010001000bfirstCompare: cmp bx,ax jg bxBigger ;condition_new_value_bigger cmp dx,bx jl dxSmaller ;condition_new_value_smallerdxSmaller: mov dx,[bx] jmp hereComesVar3 bxBigger: cmp ax,dx jne secondCompare resultBigger: mov dx,ax mov ax,[bx] jmp hereComesVar3 secondCompare: cmp ax, dx jg resultBiggerhereComesVar3: cmp bx,[VAR3] jne Var3ComesIn jmp hereComesVar4Var3ComesIn: mov bx,[VAR3] jmp firstComparehereComesVar4: cmp bx,[VAR4] jne Var4ComesIn jmp doneVar4ComesIn: mov bx,[VAR4] jmp firstComparedone: mov ebx, 0 int 0x80`

the problem is, every time I want to compile it, it always says segmentation fault.
« Last Edit: October 27, 2013, 11:21:51 PM by new_geek »

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2667
• Country:
##### Re: how to compare between two value stored in the register and get the bigger one?
« Reply #3 on: October 28, 2013, 02:25:46 AM »
Well...
Code: [Select]
`mov dx, [bx]`is what's causing the segmentation fault. You're trying to load dx with the "[contents]" of memory at the address in bx. bx, at this point, holds 0ABCDh which is not valid memory - no 16-bit value would be (in a Linux program). You just want to move the value in bx to dx:
Code: [Select]
`mov dx, bx`
There are similar errors in other places, I just picked on that one. I may have other suggestions... later. Falling asleep right now...

Best,
Frank

#### Bryant Keller

• Forum Moderator
• Full Member
• Posts: 360
• Country:
##### Re: how to compare between two value stored in the register and get the bigger one?
« Reply #4 on: October 28, 2013, 02:54:00 AM »
the problem is, every time I want to compile it, it always says segmentation fault.

I started playing around with your code and noticed a few small problems, unfortunately, once I fixed those problems the code ended up in an infinite loop. This is because registers were getting overwritten during phase 4 of your algorithm. I decided it'd be easier to provide you with an alternative (but similar) solution. I hope the comments are enough to help you follow along. This code leaves lots of room for improvement.

Code: [Select]
`section .dataVAR1: dw 30000VAR2: dw 0ABCDHVAR3: dw 7FFFHVAR4: dw 100010001000B section .bsssection .text global _start_start: nop ; TODO: your code here ;; Clear the registers we will be using. mov eax, 0 mov ebx, 0 mov ecx, 0 mov edx, 0 ;; Move our 16-bit data into our registers. mov ax, [VAR1] mov bx, [VAR2] cmp ax, bx ; Compare AX and BX jl axSmaller ; If AX < BX Then Goto axSmaller jg axBigger ; If AX > BX Then Goto axBigger ;; AX and BX are the same, so we AX to both AX and DX. mov dx, ax ; If AX = BX Then DX := AX jmp nextTestVar3axSmaller: ;; AX is smaller so: mov dx, ax ; DX := AX mov ax, bx ; AX := BX jmp nextTestVar3axBigger: ;; AX is bigger so: ; AX := AX (do nothing) mov dx, bx ; DX := BXnextTestVar3: ;; Okay, at this point AX contains the largest of VAR1/VAR2 and DX contains the smallest. ;; We need to test the next variables to see if they will overwrite the current values. mov cx, [VAR3] cmp cx, ax ; Compare CX and AX jg cxBigger ; If CX > AX Then Goto cxBigger cmp cx, dx ; Compare CX and DX jl cxSmaller ; If CX < DX Then Goto cxSmaller ;; If we reach this instruction, that means CX was ;; neither greater than AX nor smaller than DX, so we ;; just move on to the next variable. jmp nextTestVar4cxSmaller: ;; CX is smaller so: ; AX := AX (do nothing) mov dx, cx ; DX := CX jmp nextTestVar4cxBigger: ;; CX is bigger so: mov ax, cx ; AX := CX ; DX := DX (do nothing)nextTestVar4: ;; And we now we repeat the processess with VAR4 mov bx, [VAR4] cmp bx, ax ; Compare BX and AX jg bxBigger ; If BX > AX Then Goto bxBigger cmp bx, dx ; Compare BX and DX jl bxSmaller ; If BX < DX Then Goto bxSmaller ;; If we reach this instruction, that means BX was ;; neither greater than AX nor smaller than DX, so we ;; are done. jmp donebxSmaller: ;; BX is smaller so: ; AX := AX (do nothing) mov dx, bx ; DX := BX jmp donebxBigger: ;; BX is bigger so: mov ax, bx ; AX := BX ; DX := DX (do nothing)done: ;; AX = Largest, DX = Smallest ;; CHANGED: EAX contains the system call number (SYS_exit = 1) and ;; EBX contains the error code (EXIT_SUCCESS = 0). mov ebx, 0 mov eax, 1 int 0x80`
Regards,
Bryant Keller

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2667
• Country:
##### Re: how to compare between two value stored in the register and get the bigger one?
« Reply #5 on: October 28, 2013, 05:37:47 PM »
Nice catch on the missing system call number for "exit"! That would cause a segfault too. I missed that, just glancing over it.

Do we need to discuss the difference between "signed" and "unsigned" numbers? By design or by chance, we're doing signed - "jl" and "jg" are for signed numbers, "jb" and "ja" are for unsigned. Since we're doing signed numbers, VAR2 is going to be smallest (since it will be treated as a negative number) and VAR3 will be largest (it is the largest possible signed 16-bit number). If we were doing unsigned, VAR2 would be largest. You may want to explore the difference...

Again, I'm going to have to leave this for "Later"...

Best,
Frank

#### Bryant Keller

• Forum Moderator
• Full Member
• Posts: 360
• Country:
##### Re: how to compare between two value stored in the register and get the bigger one?
« Reply #6 on: October 28, 2013, 09:54:10 PM »
Do we need to discuss the difference between "signed" and "unsigned" numbers? By design or by chance, we're doing signed - "jl" and "jg" are for signed numbers, "jb" and "ja" are for unsigned. Since we're doing signed numbers, VAR2 is going to be smallest (since it will be treated as a negative number) and VAR3 will be largest (it is the largest possible signed 16-bit number). If we were doing unsigned, VAR2 would be largest. You may want to explore the difference...

Good point. I tend to ASSume numerical values are signed by default, and unsigned only when explicitly specified. This comes from the fact that I tend to count-down when looping rather than up, so I like to have ((0-1) < 0) rather than ((0-1) > 0).

#### new_geek

• Jr. Member
• Posts: 11
• Country:
##### Re: how to compare between two value stored in the register and get the bigger one?
« Reply #7 on: October 28, 2013, 10:42:50 PM »
hi, thank you for the help, frank and bryant. supposed there is a question, and my feeling is there will be one going to be asked about writing the code to compare them "unsigned"-ly?

Am i just replacing JGs and JLs with JB and JA? Sorry If I'm asking too much :|. The whole assembly language is new to me. But I kinda like it, for me, its like learning how to talk to some one using a whole new language, different set of vocabularies and things

--
best,
geek

edit: I tested the one with unassigned number rule. as the result I got var2 the bigest value and var4 the smallest, is it correct? now I'm tweaking the code right now... Thank you once again for pointing me to the direction . I'm becoming more interested in assembly now... :|
« Last Edit: October 29, 2013, 12:15:45 AM by new_geek »

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2667
• Country:
##### Re: how to compare between two value stored in the register and get the bigger one?
« Reply #8 on: October 29, 2013, 03:48:50 PM »
Glad to hear it's going better for you. I'm still having an awful time. I feel like a "clueless newbie" and an "obsolete old man" at the same time. I give myself the same advice I'd give you: "just keep slogging along"...

Your results for the unsigned comparison sound right to me. I attempted, for "extra credit", to print out the results instead of just leaving max and min in ax and dx...

Code: [Select]
`; nasm -f elf32 myprog.asm; ld -o myprog myprog.o -melf_i386section .dataVAR1: dw 30000VAR2: dw 0ABCDHVAR3: dw 7FFFHVAR4: dw 100010001000B ; the character '0' will be overwritten with the correct answer as we find itsmax db "VAR0 is signed maximum.", 10smax_size equ \$ - smaxsmin db "VAR0 is signed minimum.", 10smin_size equ \$ - sminumax db "VAR0 is unsigned maximum.", 10umax_size equ \$ - umaxumin db "VAR0 is unsigned minimum.", 10umin_size equ \$ - sminsection .text global _start_start: nop; find signed maximum, put it in ax    mov ax, [VAR1]    mov byte [smax + 3], '1'    cmp [VAR2], ax    jle skip1    mov ax, [VAR2]    mov byte [smax + 3], '2'skip1:    cmp [VAR3], ax    jle skip2    mov ax, [VAR3]    mov byte [smax + 3], '3'skip2:    cmp [VAR4], ax    jle skip3    mov ax, [VAR4]    mov byte [smax + 3], '4'skip3:; print "result"    mov edx, smax_size    mov ecx, smax    mov ebx, 1    mov eax, 4    int 80h; find signed minimum, put it in dx    mov dx, [VAR1]    mov byte [smin + 3], '1'    cmp [VAR2], dx    jge skip4    mov dx, [VAR2]    mov byte [smin + 3], '2'skip4:    cmp [VAR3], dx    jge skip5    mov dx, [VAR3]    mov byte [smin + 3], '3'skip5:    cmp [VAR4], dx    jge skip6    mov dx, [VAR4]    mov byte [smin + 3], '4'skip6:; print "result"    mov edx, smin_size    mov ecx, smin    mov ebx, 1    mov eax, 4    int 80h; find unsigned maximum, put it in ax    mov ax, [VAR1]    mov byte [umax + 3], '1'    cmp [VAR2], ax    jbe skip7    mov ax, [VAR2]    mov byte [umax + 3], '2'skip7:    cmp [VAR3], ax    jbe skip8    mov ax, [VAR3]    mov byte [umax + 3], '3'skip8:    cmp [VAR4], ax    jbe skip9    mov ax, [VAR4]    mov byte [umax + 3], '4'skip9:; print "result"    mov edx, umax_size    mov ecx, umax    mov ebx, 1    mov eax, 4    int 80h; find unsigned minimum, put it in dx    mov dx, [VAR1]    mov byte [umin + 3], '1'    cmp [VAR2], dx    jae skip10    mov dx, [VAR2]    mov byte [umin + 3], '2'skip10:    cmp [VAR3], dx    jae skip11    mov dx, [VAR3]    mov byte [umin + 3], '3'skip11:    cmp [VAR4], dx    jae skip12    mov dx, [VAR4]    mov byte [umin + 3], '4'skip12:; print "result"    mov edx, umin_size    mov ecx, umin    mov ebx, 1    mov eax, 4    int 80hdone:    mov eax, 1 mov ebx, 0 int 0x80`
At the moment, I'm not at all sure it's correct, but it "seems to work". Not necessarily the "best" way to do it.

Although it isn't written as an "array", as long as the variables stay together, it could be treated as an array and the comparisons done in a loop instead of individually. If you had 100 variables instead of just 4, you'd probably want to do that. I may take a crack at that, but... not right now...

Best,
Frank

Code: [Select]
`umin db "VAR0 is unsigned minimum.", 10umin_size equ \$ - smin`should be "\$ - umin" of course. I didn't even notice it was printing "too much" at first...

« Last Edit: October 29, 2013, 06:14:23 PM by Frank Kotler »

#### Bryant Keller

• Forum Moderator
• Full Member
• Posts: 360
• Country:
##### Re: how to compare between two value stored in the register and get the bigger one?
« Reply #9 on: October 30, 2013, 01:39:55 AM »
hi, thank you for the help, frank and bryant. supposed there is a question, and my feeling is there will be one going to be asked about writing the code to compare them "unsigned"-ly?

Am i just replacing JGs and JLs with JB and JA? Sorry If I'm asking too much :|. The whole assembly language is new to me. But I kinda like it, for me, its like learning how to talk to some one using a whole new language, different set of vocabularies and things

As Frank pointed out earlier, JG is signed and JA is unsigned for  "Jump if Greater" and "Jump if Above". Whereas JL is signed and JB is unsigned for "Jump if Lesser" and "Jump if Below". I've adjusted the code to use JA/JB as that's probably what you actually wanted. Also, I think it would be better for you to see what's going on with the registers as the program executes; so I've added a pair of macros (DUMP_INFO and DUMP_VAR) to give you a bit more information. These macros use printf.

Code: [Select]
`EXTERN printf%macro DUMP_VAR 1%push%defstr %\$var %1[SECTION .data]%%varFmt db 9, %\$var, " = %u", 10, 0 ;; We are displaying "unsigned" results (%u)__SECT__ pushad push %1 push %%varFmt call printf add esp, 8 popad%pop%endmacro%macro DUMP_INFO 1%push[SECTION .data]%%infoString db "info: ", %1, 10, 0__SECT__ pushad push %%infoString call printf add esp, 4 popad%pop%endmacrosection .dataVAR1: dw 30000VAR2: dw 0ABCDHVAR3: dw 7FFFHVAR4: dw 100010001000B section .bsssection .text global _start_start: nop ; TODO: your code here ;; Clear the registers we will be using. mov eax, 0 mov ebx, 0 mov ecx, 0 mov edx, 0 ;; Move our 16-bit data into our registers. mov ax, [VAR1] mov bx, [VAR2] DUMP_INFO "Compare VAR1 [EAX] and VAR2 [EBX]" DUMP_VAR EAX DUMP_VAR EBX cmp ax, bx ; Compare AX and BX jb axSmaller ; If AX < BX Then Goto axSmaller ja axBigger ; If AX > BX Then Goto axBigger ;; AX and BX are the same, so we AX to both AX and DX. mov dx, ax ; If AX = BX Then DX := AX jmp nextTestVar3axSmaller: ;; AX is smaller so: mov dx, ax ; DX := AX mov ax, bx ; AX := BX DUMP_INFO "EAX is smaller than EBX" DUMP_VAR EAX DUMP_VAR EDX jmp nextTestVar3axBigger: ;; AX is bigger so: ; AX := AX (do nothing) mov dx, bx ; DX := BX DUMP_INFO "EAX is bigger than EAX" DUMP_VAR EAX DUMP_VAR EDXnextTestVar3: ;; Okay, at this point AX contains the largest of VAR1/VAR2 and DX contains the smallest. ;; We need to test the next variables to see if they will overwrite the current values. mov cx, [VAR3] DUMP_INFO "Compare VAR3 [ECX] against MAX [EAX] and MIN [EDX]" DUMP_VAR ECX DUMP_VAR EAX DUMP_VAR EDX cmp cx, ax ; Compare CX and AX ja cxBigger ; If CX > AX Then Goto cxBigger cmp cx, dx ; Compare CX and DX jb cxSmaller ; If CX < DX Then Goto cxSmaller ;; If we reach this instruction, that means CX was ;; neither greater than AX nor smaller than DX, so we ;; just move on to the next variable. jmp nextTestVar4cxSmaller: ;; CX is smaller so: ; AX := AX (do nothing) mov dx, cx ; DX := CX DUMP_INFO "ECX is smaller than EDX" DUMP_VAR EAX DUMP_VAR EDX jmp nextTestVar4cxBigger: ;; CX is bigger so: mov ax, cx ; AX := CX ; DX := DX (do nothing) DUMP_INFO "ECX is bigger than EAX" DUMP_VAR EAX DUMP_VAR EDXnextTestVar4: ;; And we now we repeat the processess with VAR4 mov bx, [VAR4] DUMP_INFO "Compare VAR4 [EBX] against MAX [EAX] and MIN [EDX]" DUMP_VAR EBX DUMP_VAR EAX DUMP_VAR EDX cmp bx, ax ; Compare BX and AX ja bxBigger ; If BX > AX Then Goto bxBigger cmp bx, dx ; Compare BX and DX jb bxSmaller ; If BX < DX Then Goto bxSmaller ;; If we reach this instruction, that means BX was ;; neither greater than AX nor smaller than DX, so we ;; are done. jmp donebxSmaller: ;; BX is smaller so: ; AX := AX (do nothing) mov dx, bx ; DX := BX DUMP_INFO "EBX is smaller than EDX" DUMP_VAR EAX DUMP_VAR EDX jmp donebxBigger: ;; BX is bigger so: mov ax, bx ; AX := BX ; DX := DX (do nothing) DUMP_INFO "EBX is bigger than EAX" DUMP_VAR EAX DUMP_VAR EDXdone: ;; AX = Largest, DX = Smallest DUMP_INFO "Final MIN [EAX] and MAX [EDX] States" DUMP_VAR EAX DUMP_VAR EDX ;; CHANGED: EAX contains the system call number (SYS_exit = 1) and ;; EBX contains the error code (EXIT_SUCCESS = 0). mov ebx, 0 mov eax, 1 int 0x80`
Expected output would be:
Code: [Select]
`bryant@debian:~/Projects/new_geek\$ nasm -g -f elf main.asm -o main.o && gcc -nostartfiles -g main.o -o mainbryant@debian:~/Projects/new_geek\$ ./maininfo: Compare VAR1 [EAX] and VAR2 [EBX] EAX = 30000 EBX = 43981info: EAX is smaller than EBX EAX = 43981 EDX = 30000info: Compare VAR3 [ECX] against MAX [EAX] and MIN [EDX] ECX = 32767 EAX = 43981 EDX = 30000info: Compare VAR4 [EBX] against MAX [EAX] and MIN [EDX] EBX = 2184 EAX = 43981 EDX = 30000info: EBX is smaller than EDX EAX = 43981 EDX = 2184info: Final MIN [EAX] and MAX [EDX] States EAX = 43981 EDX = 2184bryant@debian:~/Projects\$ `
« Last Edit: October 30, 2013, 01:44:11 AM by Bryant Keller »

#### RaenirS

• Jr. Member
• Posts: 8
##### Re: how to compare between two value stored in the register and get the bigger one?
« Reply #10 on: June 17, 2014, 07:27:15 PM »
I know this is an old topic but I tried to run the code in the latest post in this thread and it gives me errors:

nasm -g -f elf 4TAq1.asm -o 4TAq1.o && gcc -nostartfiles -g 4TAq1.o -o 4TAq1
[myfilename].o: could nott read symbols: File in wrong format
collect2: error: ld returned 1 exit status

« Last Edit: June 17, 2014, 07:31:47 PM by RaenirS »

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2667
• Country:
##### Re: how to compare between two value stored in the register and get the bigger o
« Reply #11 on: June 17, 2014, 08:21:17 PM »
Hmmmm... 64-bit system, perhaps? Try adding "-m32" to gcc's command line and see if that helps any.

Best,
Frank