Search code examples
assemblyx86dos

Extending the 16-bit value to the 32-bit form in Assembly and questions about U2 code


Recently I asked a question here but it wasn't asked properly. I've read a lot but I still don't fully understand some things, but from the beginning:
I received program code written in Assembly (.COM). Adds two whole numbers together. Both numbers must be in the range [-32768..32767]. Both of these numbers must be converted from character to 16-bit form in U2 code. However, the result of this addition must be 32-bit, also in U2 (using 32-bit registers).
This code has almost 150 lines so maybe I will only include pieces of this code. I must understand each line fairly well. I can describe most of them but still don't fully understand certain lines. (lines that I don't understand are in bold)

Firstly:

         .386p          
         .MODEL TINY
      
    
 Code       SEGMENT USE16           
                            ORG 100h
.
Sign            db      0
.
    
 Start: 
                     **mov      byte ptr [Sign], 0**    ;Do I understand correctly that we set the high bit to 0 here? As positive by default 
                      xor       ax, ax                           
                      push      ax  

                         ;here (Adding: ) I understand everything, addition of 2 numbers is done and some conditions 
Adding:             
                     pop        ax          ;second number          
                     pop        bx          ;first number           
                     add        ax, bx      ;adding         
                            
                     jo     Overflow_Flag           
                     js     Sign_Flag           
                     jmp    On_ASCII    ;convert to ASCII
                
                But I don't understand this following thing. When the result of this addition is negative, we "jump" to the Sing_Flag label and ...
Sign_Flag :
                  **mov     ebx, 0ffff0000h**       ;Why are we writing mov ebx, 0ffff0000h here? 
                    add     ebx, eax                ;further I understand 
                    neg     ebx                     
                            
                    mov     dl, '-'         

    
                mov     ah, 02h                 
                int     21h                     
            
                mov     eax,ebx                 
                jmp     On_ASCII

I would like to present how I understand it:
FFFF0000h = 1111 1111 1111 1111 0000 0000 0000 0000
With this line we extend the 16-bit value to the 32-bit form. For example, the result of this addition is: -5, so:
5 = 0101 (BIN)
NEG(0101) + 1 = 1010 + 1 = 1011 = -5 (DEC)
So in this case: 0000 0000 0000 0000 1111 1111 111 1011 (neg ebx)
And that's what I don't understand/couldn't find information:

  1. Why 0ffff0000h and not e.g. 000000000h? What are these four 1s for?
  2. How does the Assembler know where the "end" of a number is? We have 1111 1111 1111 1011 and why doesn't it count the next 1?
  3. Do I understand mov byte ptr [Sign], 0?
    Thank you!

Solution

  • The first bold line initializes the variable Sign to zero. It is not used anymore in the scrap of code which you have presented, so it's hard to tell the purpose of it.

    mov     ebx, 0ffff0000h**       ;Why are we writing mov ebx, 0ffff0000h here? 
    add     ebx, eax                ;further I understand 
    neg     ebx
    

    This is unusual way how to load EBX with absolute value from AX. (I would use MOVSX EBX,AX). If the result of addition in AX is negative (-5), it jumps to Sign_Flag: with undefined garbage in the upper half of EAX. Let's assume that it was cleared before the addition, then EAX=0000_FFFBh, add it to EBX=0FFFF_0000h and now you have EBX=0FFFF_FFFBh, which is -5. After NEG EBX it gives EBX=0000_0005h which will be (together with minus sign in DL) sent on output via On_ASCII.