PDA

View Full Version : x86 ASM help please



Mike Chambers
October 11th, 2006, 09:34 PM
hi... can anybody tell me why the following code locks up the machine after i call it?


mov ax, 0b800h
mov ds, ax

mov [00h], 'A'

ret

the code runs and writes the A to the screen but it locks the system up instead of returning control to QB...

i'm calling it like this in quickbasic 4.5 (the compiled code is inside of asmCode$)


CALL ABSOLUTE(SADD(asmCode$))

like i said, it runs the bit of code and writes the data to the screen, but then locks up... shouldn't it return to QB with the RET function?

if this is a horribly stupid question, which i'm sure it is... sorry. i'm not even close to an ASM expert. :confused:

it does the same thing on every PC i use to test it... pentium 133, my 486, my 286, and even under a VMware DOS box.

chuckcmagee
October 11th, 2006, 10:38 PM
Hmmm, might "push" dx before you destroy it and pop before returning.

mbbrutman
October 12th, 2006, 05:56 AM
Yes, I second that motion.

You're altering DS which is traditionally the 'data segment' register. It is almost guaranteed to be in use by QB, and not restoring it means that QB will start referencing data structures from your video buffer, not the data segment.

And for that matter, you are also altering AX. If QB tells you that it is ok to pollute AX across calls then you don't need to save and restore it.

Instead of the push idea, I'd first look and see what other registers are available that don't have to be saved and restored. You could mov DX to one of those other registers, muck with it, and then restore it before returning. That would be faster than a push/pop pair, which requires memory access. (Moves between registers are always faster than moves to or from memory.)

ziloo
October 12th, 2006, 06:30 AM
Is it possible to run this little code under "Debug"? That way it is easy to
check out the content of all relevant registers.

DoctorPepper
October 12th, 2006, 07:20 AM
Mike,

There are quite a few sites on the web that have some good Assembler tutorials and source code. Here's one I found:

http://www.programmersheaven.com/zone5/index.htm

In addition to x86 Assembler, they also have tutorials and utilities for other CPU architectures available.

Cheers!
Howard

Mike Chambers
October 12th, 2006, 02:52 PM
Hmmm, might "push" dx before you destroy it and pop before returning.

that makes sense. like i said, i'm no ASM expert :)

so.... it should look about like this?



push ds
push ax

mov ax, 0b800h
mov ds, ax

mov [00h], 'A'

pop ax
pop ds

ret

i know i can PUSHA and POPA to do all the registers at once to be safe, but do those particular opcodes work on an 8086? i am thinking it is for 80186 or 80286, but i might be wrong.. i need to make sure all the instructions i use work on ANY x86 cpu because it's going to be going into my IRC client for DOS in QB to try to get the fastest screen write routines possible (i am putting all attribute bytes directly into the screen buffer data strings for color, etc... it will support all mIRC color and bold codes.)

chuckcmagee
October 12th, 2006, 08:22 PM
Looks much better. Is there no "mov dx,0B800h" instruction? Not sure myself as my reference books are buried. You would only worry about that if concerned with speed or space.

mbbrutman
October 13th, 2006, 04:10 PM
He's settting up the data segment register (DS), not DX, so I don't think that there is a form of MOV that can do that. It is correct as coded.

That being said, depending upon QuickBasic's calling convention, you may not need to save and restore AX. If it really is a 'call', then QB will probably assume that AX was altered. So the push ax/pop ax is probably not necessary.

Saving and restoring one extra register is no big deal. Doing it several thousand times in a row will slow things down.

chuckcmagee
October 13th, 2006, 04:34 PM
ACK! Very true on the DS vs. DX! One reason I hate Assembler. In 1969, I kept crashing an entire IBM 360 that was used by the entire University (UC Riverside, CA) because I was doing a "DEC" instead of a "INC". I finally saw it after crashing the 360 about 4 times. This was especially bad in 1969 because everyone used HASP to spool their card input and printer output. My one line screwup would trash all those spooled input jobs BEFORE they had been processing, meaning all the card decks had to be pulled from the done trays and put back thru the card reader. I finally got my super small BAL (Basic Assembler Language) deck back totally destroyed. The computer operator got mad for some reason :confused:

michal
October 23rd, 2006, 02:18 AM
hi... can anybody tell me why the following code locks up the machine after i call it?

As per GW-Basic documentation:

The following seven rules must be observed when coding a subroutine:

1. The called routine may destroy the contents of the AX, BX, CX, DX, SI, DI, and BP registers. They do not require restoration upon return to GW-BASIC. However, all segment registers and the stack pointer must be restored.

Also the ret must be a far one (encoded as CBh, a near on is C3h)


i am putting all attribute bytes directly into the screen buffer data strings for color, etc...

Well you can POKE them into the video buffer...

mbbrutman
October 23rd, 2006, 05:44 AM
GWBasic != QuickBasic 4.5

michal
October 23rd, 2006, 09:03 AM
GWBasic != QuickBasic 4.5

Well your arithmetic is obviously right :sigh: but my sixth sense tells me that the information is still relevant... I don't mean the whole docs, no, but (to quote someone else) "with just a bit of effort and discipline, it is possible and practical to code and debug in GW-BASIC, then compile your programs so as to get stand-alone EXE files using QuickBASIC". I second that (love the hands-on interaction of the interpreter).

mbbrutman
October 23rd, 2006, 09:54 AM
It would be nice to find the definitive rule on QB. I'm sure it's in the docs somewhere, so whoever needs it will eventually dig it out.

I'm a C user myself. Turbo C++ 3.0 makes it very easy to embed ASM inline and call interrupt routines. I assume that it's not too hard to link to modules done in assembler, assuming that certain register usage conventions are followed. I'd like to learn more, but I need to find an appropriate copy of Borland's Turbo Assembler first.

IBMMuseum
October 23rd, 2006, 09:55 AM
He's settting up the data segment register (DS), not DX, so I don't think that there is a form of MOV that can do that...
It can be done as:


...
mov ax, 0b800h
push ax
pop ds
...

So he can use the same relative instructions, just a different order. Sorry if the CODE thing doesn't work, but I thought I would try.

IBMMuseum
October 23rd, 2006, 10:01 AM
hi... can anybody tell me why the following code locks up the machine after i call it?


mov ax, 0b800h
mov ds, ax

mov [00h], 'A'

ret

the code runs and writes the A to the screen but it locks the system up instead of returning control to QB...

i'm calling it like this in quickbasic 4.5 (the compiled code is inside of asmCode$)


CALL ABSOLUTE(SADD(asmCode$))

like i said, it runs the bit of code and writes the data to the screen, but then locks up... shouldn't it return to QB with the RET function?

if this is a horribly stupid question, which i'm sure it is... sorry. i'm not even close to an ASM expert. :confused:

it does the same thing on every PC i use to test it... pentium 133, my 486, my 286, and even under a VMware DOS box.
Be aware for the memory reference (mov [00h], 'A') you need to tell the CPU if you use other than the default (CS) segment pointer. In Assembly this would show up something like this:


mov ds:[00h], 'A'

What do you know, the CODE thing does work as I thought.