Advertisement

MASM Assembly Help!

Started by February 07, 2015 12:35 AM
7 comments, last by NUCLEAR RABBIT 9 years, 11 months ago

Hello,

So I am currently learning MASM 8086 Assembly right now I am have trouble with an application I am attempting to mess around with and create for practice. Not sure what the errors I am getting mean (I am extremely new to assembly). Can someone please help me understand what I am doing wrong? I have attached the screenshot of the error messages and the source code. ANY help would be greatly appreciated!

age.asm


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                              ;
;   Name: Brandon                              ;
;   Date: 2/6/2015                             ;
;   Desc: Simply asks the user for their age   ;
;         and then greets the user with the    ;
;         age value they entered in            ;
;                                              ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.model small
.stack 100h

.data
age db ?
welcome_greet db 'Welcome to the GREATEST application EVER!!!', 10, 13, '$'
age_prompt db 'Please enter your age: ', 10, 13, '$'
result_prompt db 'The age you entered is: ', 10, 13, '$'
exit_prompt db 'Goodbye, hope you enjoyed this AMAZING application!', 10, 13, '$'

.code
main proc
mov AX, @DATA              ; must do everytime
mov DS, AX                 ; must also do everytime as well

lea DX, welcome_greet      ; loads the welcome_greet into the DX registery
mov AH, 9h                 ; DOS command to print a string
int 21h

lea DX, age_prompt
move AH, 9h
int 21h

move AH, 1h                ; 1h is a DOS command to read in a char
int 21h
sub AL, '0'                ; converts to an integar
move AGE, AL               ; saves the value into AGE

move AH, 9h
lea DX, result_prompt
int 21h

move AH, 2h                ; prints a char
int 21h

move AH, 04ch              ; exits the DOS application
int 21h

main endp
end main

Also, I have a few questions about the code I have. Is the DX registery only used for loading output messages into?


lea DX, welcome_greet      ; loads the welcome_greet into the DX registery
mov AH, 9h                 ; DOS command to print a string
int 21h

Like I said, I am extreme beginner to assembly so any explinations/corrections would be awesome! biggrin.png

The instruction name is "mov", not "move".


Also, I have a few questions about the code I have. Is the DX registery only used for loading output messages into?




lea DX, welcome_greet      ; loads the welcome_greet into the DX registery
mov AH, 9h                 ; DOS command to print a string
int 21h

When you use "int 21h", think of it like you're calling a function with parameters. AH is the parameter that chooses which operation to perform. DX is the argument that the AH=9 print operation uses for the string pointer to print.

But DX isn't *only* used for this. It can be used for anything else you want, too, whenever you're not about to make an int 21h call. It's a "general purpose register".
Advertisement

The instruction name is "mov", not "move".

Also, I have a few questions about the code I have. Is the DX registery only used for loading output messages into?




lea DX, welcome_greet      ; loads the welcome_greet into the DX registery
mov AH, 9h                 ; DOS command to print a string
int 21h

When you use "int 21h", think of it like you're calling a function with parameters. AH is the parameter that chooses which operation to perform. DX is the argument that the AH=9 print operation uses for the string pointer to print.

But DX isn't *only* used for this. It can be used for anything else you want, too, whenever you're not about to make an int 21h call. It's a "general purpose register".

ahhhhh, thanks for pointing out the "move" calls! rolleyes.gif


When you use "int 21h", think of it like you're calling a function with parameters. AH is the parameter that chooses which operation to perform. DX is the argument that the AH=9 print operation uses for the string pointer to print.

Thanks for that clear up. Another thing, I've been kind of thinking of the int 21h call as a 'do it' operation. Is this the right way to think about the "int 21h" call? I tried googling int 21h to find a clear explination of that operation, but had no luck :/ If so, how does the "int 21h" call know which lines I want it to "do"?

move AH, 9h


"move" is not a valid opcode.

Additionally, i would recommend learning 32 bit assembly, as 16 bit assembly is pretty much not used anywhere and the architecture of 16 bit mode is pretty much replicated nowhere (so the knowledge isn't even useful on other platforms for the most part)

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.


how does the "int 21h" call know which lines I want it to "do"?

int 21h, when AH==9, uses the address in DX as a pointer to a string.

As Nypryren mentions, think of int 21h as:


if( AH==9 ) print the characters at the address in DX (until a stop character '$' is encountered)

I don't know if you're familiar with a switch() statement, but int 21h is sort of like:


; int 21h
switch( AH )
{
   case 9:
      get the address stored in register DX;
      print the characters at DX, DX+1, etc., until '$' is encountered
      return
   case (another value):
      do something else
      return
   case ...
}

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.


how does the "int 21h" call know which lines I want it to "do"?

int 21h, when AH==9, uses the address in DX as a pointer to a string.

As Nypryren mentions, think of int 21h as:


if( AH==9 ) print the characters at the address in DX (until a stop character '$' is encountered)

I don't know if you're familiar with a switch() statement, but int 21h is sort of like:


; int 21h
switch( AH )
{
   case 9:
      get the address stored in register DX;
      print the characters at DX, DX+1, etc., until '$' is encountered
      return
   case (another value):
      do something else
      return
   case ...
}

Thank you so much that was an awesome explination! Im coming from Java and C/C++ so that was perfect

Advertisement

Another thing, I've been kind of thinking of the int 21h call as a 'do it' operation. Is this the right way to think about the "int 21h" call? I tried googling int 21h to find a clear explination of that operation, but had no luck :/ If so, how does the "int 21h" call know which lines I want it to "do"?


INT is sort of like a CALL instruction that does some extra stuff. Kind of like how CALL is just a JMP that does extra stuff.

Somewhere in memory, there is an "interrupt vector table" (IVT for short) which is just an array of function pointers. The INT instruction looks up an entry in that table (using the numeric operand you gave to INT as the index) and then uses the address in the array to call a function.

Back when I used DOS in real mode, the IVT was at memory address zero.

"But who creates the IVT", you ask? The BIOS does, at system startup. You can read more about the gory details here:

http://wiki.osdev.org/System_Initialization_(x86)


After INT has found the address and called the function, the function itself works just like what Buckeye posted.

Looks like most of the important bits were covered, but there are some loose ends.

The first and very important bit is that all of those commands are dead or dying. While Ralph Brown's Interrupt List is useful for hardware developers and for developers in the 1980s and 1990s, today in 2015 it is mostly historical.


That said, if you are doing DOS based programming, that old masm assembler can be a fun way to learn lower level programming. You'll probably need a DOS emulator like dosbox if you want to have most of the old functionality, but I'll assume you've got all that.


Interrupt 21h is the DOS general functionality interrupt.

Hundreds of pieces of DOS functionality were tied into that interrupt. Exactly what functionality took place depends on the contents of the AH register.

For example:
01h reads a byte from standard input
02h writes a byte to standard output
09h writes a string to standard output (as you discovered)
2Ah reads the system date
2Bh sets the system date
2Ch reads the system time
2Dh sets the system time
39h creates a disk directory
3Ah deletes a disk directory
3Ch creates a file
3Dh opens a file
3Eh closes a file

And on and on.

There are/were interrupts for every piece of functionality provided by the OS and the hardware. Graphics hardware was generally accessed through interrupt 10h and various ports and memory blocks. The mouse was generally accessed through interrupt 33h.

One of my favorite little bad hacks was to open edlin (a very simple line editor) jump to position 100 (where command executables start) and enter the two bytes cd19. Then save it as a .com file. CD is the bytecode for 'interrupt', I'll let you look up interrupt 19h. Then I'd call the command in their autoexec.bat file, before any TSRs were loaded. Fun times were had by many, but not all.

Anyway, back on track.

Almost every interrupt will expect some values loaded into registers. The system would document those. Back in the 1980s many computers came with manuals that documented all or most of the overriden interrupts and their parameters. Devices like printers and modems would also include details of their command codes and escape sequences. It was cryptic to most people, but necessary for developers and system administrators in order to customize the software and hardware to run together.

You as the programmer could then look up the functionality you needed. If you wanted to change the graphics mode you would set the right parameters to indicate the graphics mode, then call interrupt 10h, and when it returned it would load the status codes. If you wanted to read the mouse coordinates you would set the right parameters to indicate what you wanted to read, and when it returned it would load the mouse position.


As others have pointed out, this is rather dated. Most of these are virtualized on modern hardware, you have your own little sandbox you are playing in and a private little interrupt table is established for your application. Many of the old 16-bit function DOS calls no longer work as Microsoft declared years ago "DOS is dead." But in practice it is not as dead as they had hoped.

Another thing, I've been kind of thinking of the int 21h call as a 'do it' operation. Is this the right way to think about the "int 21h" call? I tried googling int 21h to find a clear explination of that operation, but had no luck :/ If so, how does the "int 21h" call know which lines I want it to "do"?


INT is sort of like a CALL instruction that does some extra stuff. Kind of like how CALL is just a JMP that does extra stuff.

Somewhere in memory, there is an "interrupt vector table" (IVT for short) which is just an array of function pointers. The INT instruction looks up an entry in that table (using the numeric operand you gave to INT as the index) and then uses the address in the array to call a function.

Back when I used DOS in real mode, the IVT was at memory address zero.

"But who creates the IVT", you ask? The BIOS does, at system startup. You can read more about the gory details here:

http://wiki.osdev.org/System_Initialization_(x86)


After INT has found the address and called the function, the function itself works just like what Buckeye posted.

Sweet, thank you for the explination and link! gonna read that in a few mins biggrin.png

Looks like most of the important bits were covered, but there are some loose ends.

The first and very important bit is that all of those commands are dead or dying. While Ralph Brown's Interrupt List is useful for hardware developers and for developers in the 1980s and 1990s, today in 2015 it is mostly historical.


That said, if you are doing DOS based programming, that old masm assembler can be a fun way to learn lower level programming. You'll probably need a DOS emulator like dosbox if you want to have most of the old functionality, but I'll assume you've got all that.


Interrupt 21h is the DOS general functionality interrupt.

Hundreds of pieces of DOS functionality were tied into that interrupt. Exactly what functionality took place depends on the contents of the AH register.

For example:
01h reads a byte from standard input
02h writes a byte to standard output
09h writes a string to standard output (as you discovered)
2Ah reads the system date
2Bh sets the system date
2Ch reads the system time
2Dh sets the system time
39h creates a disk directory
3Ah deletes a disk directory
3Ch creates a file
3Dh opens a file
3Eh closes a file

And on and on.

There are/were interrupts for every piece of functionality provided by the OS and the hardware. Graphics hardware was generally accessed through interrupt 10h and various ports and memory blocks. The mouse was generally accessed through interrupt 33h.

One of my favorite little bad hacks was to open edlin (a very simple line editor) jump to position 100 (where command executables start) and enter the two bytes cd19. Then save it as a .com file. CD is the bytecode for 'interrupt', I'll let you look up interrupt 19h. Then I'd call the command in their autoexec.bat file, before any TSRs were loaded. Fun times were had by many, but not all.

Anyway, back on track.

Almost every interrupt will expect some values loaded into registers. The system would document those. Back in the 1980s many computers came with manuals that documented all or most of the overriden interrupts and their parameters. Devices like printers and modems would also include details of their command codes and escape sequences. It was cryptic to most people, but necessary for developers and system administrators in order to customize the software and hardware to run together.

You as the programmer could then look up the functionality you needed. If you wanted to change the graphics mode you would set the right parameters to indicate the graphics mode, then call interrupt 10h, and when it returned it would load the status codes. If you wanted to read the mouse coordinates you would set the right parameters to indicate what you wanted to read, and when it returned it would load the mouse position.


As others have pointed out, this is rather dated. Most of these are virtualized on modern hardware, you have your own little sandbox you are playing in and a private little interrupt table is established for your application. Many of the old 16-bit function DOS calls no longer work as Microsoft declared years ago "DOS is dead." But in practice it is not as dead as they had hoped.

Awesome explination and thanks for a short desc of some other interrupt calls, I think I am begining to understand things better! About your cd19 and autoexec.bat hack, did that allow you to control their ROM utilities? haha I looked it up and I read a little about the bootstrap loader.

About this being 16 bit DOS and to learn 32 bit instead, I wish I could because it sounds like its more useful in this day and age, but the reason I am learning it is because it's a required class I need to go toward my CS degree. However my instructor said this semester might be the last semester he teaches this course. All we have done is a "Hello World" application so far, so I am just trying to learn some stuff on my own.

Once again I want to thank everyone for your explinations and help! cool.png

This topic is closed to new replies.

Advertisement