2

For science fair, I need three programs that count to 50,000 and output each number as they do, I need one in c++, one in java, and one in assembly. I have the c++ and java programs, but I don't see what I'm doing wrong for my assembly code:

    [org 0x100]
    [bits 32]

    mov ax, 0
    mov bx, target
    jmp start

    start:
    mov cx, 0x01
    add ax, cx
    mov dx, ax
    mov ah, 09
    int 0x21
    mov ax, dx
    cmp ax, bx
    jg term
    jmp start

    term:
    mov dx, msgT
    mov ah, 09
    int 0x21
    mov ah, 00
    int 0x21

    msgT db 'Terminating'
    target dw 50000

I am using the assembler NASM, and right now, it counts to 50,000 but doesn't output each number as it calculates them.

JAW1025
  • 676
  • 2
  • 8
  • 17
  • On what platform are you running this? – Pascal Cuoq Nov 06 '11 at 15:13
  • sorry I forgot to include that. I'm running it on windows 7 – JAW1025 Nov 06 '11 at 15:14
  • 3
    If you're trying to make a 16-bit MS-DOS com file, you should be using `[bits 16]`. And as @Vlad says AH=09h takes a string in DX not a number (see e.g. [here](http://stackoverflow.com/questions/7863094/how-can-i-convert-hex-to-decimal/7865387#7865387) on how to convert a number to string, also note that you'll have to `$`-terminate the string instead of NUL-terminate it). – user786653 Nov 06 '11 at 15:21
  • So using the above method, you'd just change bufferend: db 0 to bufferend: db $, then go on doing what he suggested? – JAW1025 Nov 06 '11 at 16:30

3 Answers3

3

Copied from my comment:

If you're trying to make a 16-bit MS-DOS com file, you should be using [bits 16]. And as @Vlad says AH=09h takes a string in DX not a number (see e.g. here on how to convert a number to string, also note that you'll have to $-terminate the string instead of NUL-terminate it).

Some other things:

  • mov bx, target moves the address of target to bx. You wanted: mov bx, [target].
  • jg term is branching based on signed comparison (you're effectively comparing ax to -15536). You want ja term.
  • You need to make sure to preserve the number, keeping it in a register requires extreme care. It's easier to just save it on the stack.

The basic structure of your program should be something like this:

    [org 0x100] ; DOS .COM files are loaded at CS:0100h
    [bits 16]   ; And are 16-bits

start:
    mov ax, 0          ; The current count
printloop:
    push ax            ; Save current number 

    call myconvertfunc ; Some function to convert a number in ax and return a '$'-terminated string in dx
    mov ah, 0x09
    int 0x21

    mov dx, newline    ; Point dx to newline string
    mov ah, 0x09       ; Print $-terminated string in dx
    int 0x21

    pop ax             ; Restore current number

    inc ax             ; Next number 
    cmp ax, 50000      ; Compare number to the maximum number 
    jbe printloop      ; Notice branching based on unsigned comparison is needed

    mov ax, 0x4c00     ; Return 0. AH=4Ch AL=Return value
    int 0x21

newline: db 13, 10, '$' ; String containing "\r\n$"
Community
  • 1
  • 1
user786653
  • 29,780
  • 4
  • 43
  • 53
  • Thanks for the help, I now see my mistakes, and I will give your method a try. – JAW1025 Nov 06 '11 at 17:28
  • Is there a way to increment Si to the end of a string? I need it for the 'my convert func'. – JAW1025 Nov 06 '11 at 20:22
  • Do you mean like `inc si` or the equivalent `add si, 1` or do you want to increase the value in the address pointed to by si? in that case it's `inc [si]`. Or move to the end of the string? that's just a loop incrementing `si` and doing `cmp [si], SOME_VALUE` to check if the end is reached. – user786653 Nov 06 '11 at 20:28
  • the reason I want to increment the address of si to the end of the string, is to write the '$' to the end of it. Is there some other value to do that? – JAW1025 Nov 06 '11 at 22:14
1

I think you are not doing the printing properly.

This here says that with Int 21/AH=09h you print a $-terminated string, which neither your string nor your numbers seem to be.

It might be necessary to code your own number printing, digit by digit, perhaps with Int 21/AH=02h.

Vlad
  • 18,195
  • 4
  • 41
  • 71
  • I'm right when thinking that when it says that al is the last character output, that I would put in al the last character. – JAW1025 Nov 06 '11 at 15:17
  • I think what they're saying is that after you call `int 0x21` with `ah=02h` you end up with the character in `al`, but you'd have passed it in `dl`. For string printing, it will leave the `$` in `al` at the end. I'm assuming the routines use `al` throughout their processing and don't bother with restoring it. – Vlad Nov 06 '11 at 15:19
  • Ok, so how would I do this? I get the concept that al is the last value to be printed, so when dl = al it will print that then stop, but how would I put a value in dl, when the whole number is being stored in ax? – JAW1025 Nov 06 '11 at 15:22
  • If I read it correctly, `al` is incidentally the last value that _was_ printed, rather than the last value _to be_ printed. It's an output, rather than an input. In any case, one way to get the last digit of a number `n`, is `n mod 10`. Then to slice that off you can do `n = n/10;`. It gets messy because you'd be getting your digits in reverse, but you get the picture. – Vlad Nov 06 '11 at 15:28
  • so to get the last value of the number you'd do n = n mod 10 and then to slice the value off you'd do n = n/10. So to get the value of a two digit number you'd do n = n mod 10, then print that, then do n = n mod10 , n = n/10 and print that? – JAW1025 Nov 06 '11 at 16:23
  • This way you'll get your digits in reverse, so you should probably buffer them. @user786653 links to a conversion routine, but if this is homework, you'd be better off trying to code it up on your own before you follow the link. – Vlad Nov 06 '11 at 16:41
0

Wait, assembly is not synonym for old dusty stuff that nobody uses.

If it's for a fair: you need to show some innovation. (16 bit dos assembly on win7 is the opposite of that)

You have no requirements other than go to the fair and use your win7 computer?

  • If your OS is 64bit

use goasm it's complete with IDE and the community is huge.

  • If you're on 32bit

go with masm32 and winasm.

I'm all for using old school assembly, but please don't make 16bit programs on windows 7 and try to use the windows api instead of interrupts. (the code generated will still be around 4kb if that's what you need to show at the fair)

龚元程
  • 417
  • 1
  • 5
  • 14
  • For the fair, all I need is to make a 16bit program that runs command line style, but I will look into masm32 and winasm. What makes them different? Does it just make windows api avalaible> – JAW1025 Nov 07 '11 at 13:00
  • @JAW1025: Not much I can say in a comment, but 32 bit assembly (not only masm) lets you use the power of 32bit registers (eax...etc) and you can use the windows api. Winasm gives you the power of a full development environment. However, if the requirement is to use 16bit asm then you can forget about it. Maybe you can include some library to avoid the pain of using interrupts. (find Irvine16.inc). Did you solve your problem above? – 龚元程 Nov 07 '11 at 13:38
  • The requirement for my experiment is to use a 16 bit assembly program, however from now on when I write software in assembly, I'll try to use 32 bit. Whats the difference between ax and eax is it literally that ax is only 16 bits where eax is 32 bits? and yes I have solved my above problem (I think, I still have to get time to compile it, and fix the problems.) – JAW1025 Nov 07 '11 at 21:16