Author Topic: how print the value  (Read 25588 times)

Offline DarkC0de

  • Jr. Member
  • *
  • Posts: 3
how print the value
« on: May 07, 2010, 09:02:10 PM »
hi
i have this program and i want to print this number

Code: [Select]
[org 0x0100]
mov bx, num1 ; point bx to first number
mov cx, 5 ; load count of numbers in cx
mov ax, 0 ; initialize sum to zero
l1:
add ax, [bx] ; add number to ax
add bx, 1 ; advance bx to next number
sub cx, 1 ; numbers to be added reduced
jnz l1 ; if numbers remain add next


mov [total], ax ; write back sum in memory
mov dx ,total
;sub dx,30h

mov ah,02h
int 21h
mov ax, 0x4c00 ; terminate program
int 21h
num1: db 10,20,30,40,50
total: dw 0

I want to print all value in num1 and the value in total [/size][/size][/size]

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how print the value
« Reply #1 on: May 07, 2010, 11:23:40 PM »
Well... different ways... "just call printf" is popular. :)

This isn't a very "good" way, but I think it's easier to understand than any of the "good" ways...

Code: [Select]
;--------------
ax2dec:
    push ax
    push bx
    push cx
    push dx

    mov bx, 10          ; divide by ten
    xor cx, cx          ; zero our counter
.push_digit:
    xor dx, dx          ; clear dx for the div
    div bx              ; dx:ax/bx -> ax quotient, dx remainder
    push dx             ; save remainder
    inc cx              ; bump digit counter
    or ax, ax           ; is quotient zero?
    jnz .push_digit     ; no, do more

    mov ah, 2           ; print character subfunction
.pop_digit:
    pop dx              ; get remainder back
    add dl, '0'         ; convert to ascii character
    int 21h             ; print it
    loop .pop_digit     ; cx times

    pop dx
    pop cx
    pop bx
    pop ax
    ret
;-------------------

It isn't going to give you the result you expect. "add ax, [bx]" adds *two* bytes to ax, and your numbers are defined as bytes. If you changed to "num1: dW 10, 20, 30,..." it would work, but you'd want to add 2 to bx to get to the next one. You could use bytes throughout ("add al, [bx]"). This particular list of numbers won't overflow a byte, but the next one might. Any guidance in the "assignment" what size numbers you're supposed to handle?

It *is* possible to add an array of bytes to a word total. The "movzx" and "movsx" (for signed numbers) might help, but you're probably not "supposed" to know them yet. You could do...

Code: [Select]
   mov ah, 0  ; make sure upper bits of ax are zero
   mov dx, 0  ; initialize sum to zero
   mov cx, 5
   mov bx, num1
addloop: ; I gave it a different name :)
   mov al, [bx]
   add dx, ax  ; dx looks unemployed...
   add bx, 1
   sub cx, 1
   jnz looptop

...

Note that you can't use the same register for "sum" as you use to fetch the number from the array, if you do it this way... ("add [total], ax" will work, if you don't want to use another register...).

Do you see why you've got a problem there, and how to solve it?

Best,
Frank


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how print the value
« Reply #2 on: May 08, 2010, 04:44:05 PM »
I missed an easy way to fix the "problem" with your code. Gettin' slow! :)

Code: [Select]
mov bx, num1 ; point bx to first number
mov cx, 5 ; load count of numbers in cx
mov ax, 0 ; initialize sum to zero
l1:
add al, [bx] ; add number to ax
                adc ah, 0
add bx, 1 ; advance bx to next number
        ...

Are you familiar with the "adc" instruction? You'll never learn any younger.

Best,
Frank


Offline DarkC0de

  • Jr. Member
  • *
  • Posts: 3
Re: how print the value
« Reply #3 on: May 08, 2010, 09:31:57 PM »
Quote
Do you see why you've got a problem there, and how to solve it?
Yes of course  divide the sum in ax by 10 and save the quotient in ax and the remainder in dx and push the dx in stack  . loop  ;D ;D

thanks  now I understand a lot of operations and where is done

for the adc it's something like addition with carry  for the flag cf 

but actual I don't understand what use it for :)

finally this my code

Code: [Select]
; a program to add ten numbers
[org 0x0100]
mov bx , number
mov ax , 0
mov cx , 2

addloop:
add ax , [bx]
add bx , 2
sub cx , 1
jne addloop

mov bx , 10
mov cx , 0
savedata:
mov dx , 0
div bx          ;dx:ax/bx -> ax quotient, dx remainder
push dx
inc cx
cmp ax , 0
jne savedata

mov ah , 2

print:
pop dx
add dl , 30h
int 21h
sub cx , 1
jne print

mov ax ,4c00h
int 21h


number : dw 10, 20 ,30, 40, 50, 60, 70, 80, 90, 100

again thanks for this help  ,if you know a good tutorial please tell me

beast wishes

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how print the value
« Reply #4 on: May 09, 2010, 06:51:11 AM »
Hmmm... I don't see how you put 2 in cx and claim to be adding ten numbers! :)

But okay, looks good otherwise. The array of numbers you use won't overflow ax, but another array of numbers might. What would happen? "add ax, [bx]" would "wrap around" - 65535 + 1 = 0. This is "correct", we're doing modular arithmetic, but it probably isn't what the user expects. The carry flag is set if this happens, so "jc overflow" after the add would solve the problem. Or... we could "keep going" - "adc dx, 0" to make a 32-bit number in dx:ax (printing it is a PITA). A 32-bit number could overflow, too, so we'd better "jc really_bad_overflow" after the adc. Or we could keep going... "adc cx, 0"... oops, we're using cx... well, use memory when we run out of registers. This is how a "bignum" routine works, in fact. Unlike the C concept of "int", "the integers" are an infinite set of numbers, so you'll run out of memory before you run out of numbers... so we need to be prepared to print "overflow, sorry" at some point, no matter what we do. :(

The example I posted, assuming we were adding bytes to a word "sum" is the same thing in small scale. Another example (from the same file, as it happens - *that* was easy to find! :) )... suppose we wanted to display a number in binary - I don't think printf has an option for this! (kinda useless - once we're comfortable with hex, we can "see" where the bits are without having 'em printed out...) In this case, the carry flag isn't being set by an "overflow", but is set/cleared by having a bit from the "number" shifted (or rotated) into it, and the "adc" is used to bump the character '0' to the character '1', if it's set...

Code: [Select]
;--------------------------
ax2bin:
    push cx
    push dx
    mov cx, 16
.top
    rcl ax, 1     ; rotate and set/clear carry
    mov dl, '0'
    adc dl, 0     ; make it '1' if carry set

    push ax
    mov ah, 2     ; print it
    int 21h
    pop ax

    loop .top

    pop dx
    pop cx
    ret
;----------------------------

"sbb" (subtract with borrow) is the "opposite" instruction - the "borrow flag" is the same thing as the "carry flag". There are some "tricks" involving sbb that can be used to eliminate conditional jumps (no examples on me, at the moment). The most common(?) use of adc/sbb is probably in "bignum" routines.

The best(?) tutorial using Nasm syntax is probably Dr. Paul Carter's http://www.drpaulcarter.com/pcasm Several other posters seem to be using it (in a class, apparently). (I don't know if they're having trouble in spite of having read the material, or because they haven't read the material. :) If you joined in, you'd have company, at least. In a way, it would be a step backwards for you - he provides a "print_int" routine that does what you're doing now. When the time comes to ditch the "training wheels", you'll be prepared! We've got a guy struggling with octal in a nearby thread - similar problems crop up... A possible disadvantage - if you don't already have a C compiler installed, you'll need one.

Jeff Duntemann's latest edition of "Assembly Language Step by Step" is out. It uses Nasm syntax, but Linux. His second edition uses dos, mostly, if you want to stick to dos. The first edition is Masm syntax. He's makin' progress! :)

I also like the "low level" approach in Jonathan Bartlett's "Programming From the Ground Up". Gas (AT&T) syntax, and Linux. Possibly not what you're looking for.

Randy Hyde's old, obsolete, 16-bit dos version of "Art of Assembly" is probably the most extensive tutorial you'll find. Masm syntax. The new AoA uses HLA as an assembler. Very different syntax. Not my cup 'o tea, but some people like it. Pity I don't like the syntax, because it's an excellent tutorial - portable between Windows, Linux, BSD, MacOSX... Randy provides his own library for all these, rather than "just call printf" (which is how Dr. Carter does it). Disclaimer: when the going gets tough, Randy does call libc in a few spots. His latest work, "HOWL" ("I saw the best minds of my generation destroyed by madness!" - sorry, couldn't help it), the HLA Object Windows Library looks... interesting... although I don't think OOP is "my thing", either. Massive amout of work has gone into all this! Won't hurt you to look at it...

http://homepage.mac.com/randyhyde/webster.cs.ucr.edu/

and his new tutorial, if Windows is your thing:

http://homepage.mac.com/randyhyde/webster.cs.ucr.edu/Win32Asm/index.html

Wash your hands after. :)

I don't mean to rush you to abandon dos - it isn't a bad way to start learning assembly language - but you'll want to "graduate" to 32-bit code soon. It's a lot easier, in some ways. We all need to get into 64-bit code sometime - only a few "pioneers" have delved into it - not including me. It doesn't look any easier to me. But the world changes, and we have to keep up (or not). When you're ready...

Best,
Frank


Offline DarkC0de

  • Jr. Member
  • *
  • Posts: 3
Re: how print the value
« Reply #5 on: May 09, 2010, 09:39:33 PM »
Quote
I don't see how you put 2 in cx and claim to be adding ten numbers!

 ??? ??? ??? huh  just Mis-writing


thanks Frank

I don't now what I can say