NASM - The Netwide Assembler

NASM Forum => Using NASM => Topic started by: codeferever on September 15, 2010, 04:39:40 AM

Title: how to change as86 assember that nasm needed
Post by: codeferever on September 15, 2010, 04:39:40 AM
hi,I'm new here!
when I was reading linux0.12 kernel,I have found a simple assember.but there is only nasm and alink in my computer :(
how to change it?please help me.
Code: [Select]
!
! boot.s
!
.globl begtext,begdata,begbss,endtext,enddata,endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
BOOTSEG = 0X07C0

entry start
start:
        jmpi go,BOOTSEG
go: mov ax,cs
mov ds,ax
mov es,ax
mov [msg1+17],ah
mov cx,#20
mov dx,#0x1004
mov bx,#0x00c
mov ax,#0x1301
int 0x10
loop0: jmp loop0
msg1: .ascii "Loading system..."
.byte 13,10
.org        510
.word 0xAA55
.text
endtext:
.data
enddata:
.bss
endbss:
Title: Re: how to change as86 assember that nasm needed
Post by: Frank Kotler on September 15, 2010, 09:57:13 AM
Doesn't take too much changing, actually...

Code: [Select]
; nasm -f bin -o boot.bin boot.asm

org 0

section .text

BOOTSEG equ 0X07C0

        jmp go:BOOTSEG
go: mov ax,cs
mov ds,ax
mov es,ax
mov [msg1+17],ah
mov cx, 20
mov dx, 0x1004
mov bx, 0x00c
mov ax, 0x1301
int 0x10
loop0: jmp loop0
msg1: db "Loading system...",13,10

times 510 - ($ - $$) db 0
dw 0xAA55

Next I suppose you'll want to know why it doesn't work? Fails to put msg1 in bp before the interrupt. Untested, but I think that's right...

Happy Bootin',
Frank

Title: Re: how to change as86 assember that nasm needed
Post by: codeferever on September 17, 2010, 09:29:43 AM
so nice!I have learned how to use Bochs these days,and finally the simple boot run successfully!
but Frank,your code does not work,why?It says that no bootable device.
after that,I have revised it.although it works well before 0x7c00,it cannot show anything... :(
at last the code works well like this:
Code: [Select]
; nasm -f bin -o boot.bin boot.asm

org 07c00h

mov ax,cs
mov ds,ax
mov es,ax
call go
loop0:jmp loop0
go:
  mov ax, msg1                   
  mov bp, ax ;
mov cx, 40 ;
  mov ax, 1301h ;                 
  mov bx, 000ch ;
  mov dx, 1104h                     
  int 10h ;

msg1: db "Happy Booting! Loading system..."
times 510 - ($ - $$) db 0 ;make the bin 512 Bytes
dw 0xaa55 ;0xAA55 at the end of this file!
Title: Re: how to change as86 assember that nasm needed
Post by: Frank Kotler on September 17, 2010, 11:23:43 AM
Good! Maybe someday I'll figure out how to use Bochs. So far, I have not.

I'm not too surprised that my code doesn't work. (My attempt to translate the as86 code that you provided, that is.) There's a lot that could be wrong with it. I don't know why Bochs would consider it "not a bootable device". In "real hardware", one bios differs from another. Lack of the boot signature could cause a bios to consider it "not a bootable device". I have heard of, but not encountered, a bios which refuses to boot if the first byte is not a "jmp" - "jmp near" or "jmp short"/"nop", I don't think a far jump will do it. My bios appears to be a "slut" and will boot anything - even without the boot sig! Bochs is probably "configurable", if you know what you're doing.

The as86 code starts with a far jump (if I'm reading it right). Thus, when we do "mov ax, cs", we know what's in cs (7C0h). Your code eliminates the far jump, and ASSumes that cs is zero. This is a pretty good assumption. There are reports, mere "rumors" perhaps, of a bios that jumps to 7C0h:0 rather than 0:7C00h. Zero is a pretty good bet, but if I were trying to write a "universal" bootsector, I would use an explicit zero (with "org 7C00h") or, as the as86 code does, an explicit 7C0h (with "org 0" - Nasm's default, but I would specify it "for clarity").

Anyway, good start! Now that you've claimed that you're "Loading System", what are you going to load? (this is the part where I get stuck!)

Best,
Frank

Title: Re: how to change as86 assember that nasm needed
Post by: codeferever on September 21, 2010, 03:57:08 PM
what should me load,a system?I really want to gives out my own system on my 23's birthday,seems  like Linus,cool,if so,there are only 3 years left! :D
But how to start this job?Oh,so terrible to think with it!

Title: Re: how to change as86 assember that nasm needed
Post by: codeferever on September 23, 2010, 05:28:11 AM
Code: [Select]
org 100h

mov ah,9
mov dx,msg
int 21h

;well,if the address is 0xb800
;I want to write msg there...
;and it works as "int 21h" without BIOS

mov ah,8
int 21h

msg:db "HW$"
Title: Re: how to change as86 assember that nasm needed
Post by: Frank Kotler on September 23, 2010, 07:11:00 AM
Well, I'm confused, Codeferever. We started out with some as86 bootsector code, and somehow slid into a dos .com file. Not a bad idea to get some stuff working as a "dosless .com file" before you try to load it from a bootsector, so here's a .com file that writes the message to 0B800h. Note that this is a segment address - the physical address would be 0B8000h.

Code: [Select]
;---------------------------------
; nasm -f bin -o hwnoint.com hwnoint.asm

org 100h

    push word 0B800h    ; segment of video memory
    pop es              ; (because stosw uses es:di)
    mov di, (10 * 80 + 30) * 2  ; offset into screen
        ; (row * width + column) * 2 bytes/character
    mov si, msg         ; offset of our string
    mov ah, 0B0h        ; color (blinking black on cyan)
top:
    lodsb               ; get byte from [ds:si] into al
                        ; and increment si for next one
    or al, al           ; this doesn't change al, but sets
    jz depart           ; the flags - if zero, we're done
    stosw               ; stores ax (char & color) to [es:si]
                        ; and add 2 to di for next one
    jmp short top       ; do more
depart:
    ret                 ; return to dos (or other caller)

msg db " Look, Ma! No ints! ",0  ; note 0, not '$', terminated
                                 ; '$' is just for int 21h/9
;------------------------------------

This is somewhat deceptive code - it claims "no interrupts", but ends in a "ret". Since dos has pushed a zero on the stack when it loads us, this "ret" returns us to offset zero in our current segment... where dos has placed "CD 20", as the first thing in the Program Segment Prefix. This is "int 20h", and returns us to dos, so there's a "hidden interrupt" involved. This will not work if loaded from a bootsector! (I've been known to put "CD 19" where dos puts the "CD 20" to reload system - not really the same thing.)

Sorry I didn't notice it sooner, there's an error in the last boot code you posted. You "call go", but "go" doesn't end with a "ret", so you never return to the "loop0: jmp loop0". Easily fixed.

The dos code you just posted doesn't "exit back to dos" properly, either - it just "falls through" and attempts to execute your message. This probably won't format your hard drive or do other damage, but you really ought to exit properly, just in case!

If you're writing your own "system", you'll probably want to provide some kind of a "shell" to exit back to (Linux usually uses "bash", "command.com" for dos) - "loop0: jmp loop0" is okay for testing.

Anyway, the above should write a message to 0B800:????, which I guess is what you wanted(?)...

Best,
Frank

Title: Re: how to change as86 assember that nasm needed
Post by: Maryjane on September 24, 2010, 10:40:57 AM
when I was reading linux0.12 kernel,I have found a simple assember.but there is only nasm and alink in my computer.
Thank you for the sensible critique. Me & my neighbour were preparing to do some research about that. We got a good book on that matter from our local library and most books where not as influensive as your information. I am very glad to see such information which I was searching for a long time.This made very glad because in my language, there are not much good source like this.
sim loc phat (http://www.chosimsodep.net/sim-than-tai-sim-loc-phat-sim-ganh-dao-sim-nam-sinh)   viec lam (http://www.vieclamtuyendung.net/viec-lam-nhanh-kiem-viec-tuyen-dung-tim-viec-nhanh/)
Title: Re: how to change as86 assember that nasm needed
Post by: codeferever on September 24, 2010, 12:21:56 PM
Thank you , Frank.
But I really don't know where could I find these information,like the address 0xb8000 and the parallel port address 03bch...
as we know,there is a vector table at the physical address 0000h(wrong?),so if we can change something like this:
Code: [Select]
push 0
pop es
mov word ptr [es:vector*4],oper_addr
mov word ptr [es:vector*4+2],0
;if nasm compile like this?
;then we can use "int xh" which point to a new address?
 
well,what's in dos,when it was powed on?

consider code that output a byte to athe parallel port:
in Intel format used by the BIOS or the bootloader
Code: [Select]
mov dx,03bch
mov a,0abh
out dx,al
rewrite the preceding snippet using GCC inline assembly,which will be used from the protected mode kernel
Code: [Select]
unsigned short port = 0x3bc;
unsigned char data = 0xab;

asm(
"outb %%al,%%dx\n\t"
:
:"a"(data),"d"(port)
);
so,how the nasm uses a functiom in a C file?









Title: Re: how to change as86 assember that nasm needed
Post by: Frank Kotler on September 24, 2010, 02:08:11 PM
Well, you can get a lot of information about memory and ports and interrupts from Ralf Brown's Interrupt List:

http://www.ctyme.com/rbrown.htm

That's an online site... You might be better off to download the whole thing:

http://www.cs.cmu.edu/~ralf/files.html

Besides the "interrupt list" itself there's a memory list, ports list... lots of stuff you may find useful.

At bootup, the interrupt vector table is at physical address zero - but it can be relocated. In dos there are a couple of int 21h functions (25h and 35h ???) to get and set IVT addresses... but I take it this isn't really for dos... You seem to have the general idea right. You might want to save the old vector before replacing it. Might want to cli/sti around it so an interrupt doesn't occur with it half changed(!).

I don't know much about gcc inline syntax - I guess that's right. Now you want to call this C function from Nasm? (Why?) Just put "extern the_C_function" in the Nasm code, and call it. Link the Nasm-produced .o file with the gcc-produced .o file. (if this were "user" code for Linux, you'd have to get permission to access the port first, or it would segfault... but I take it it isn't...)

Best,
Frank

Title: Re: how to change as86 assember that nasm needed
Post by: codeferever on September 27, 2010, 12:38:54 PM
yeah,it is a very great job!
Looks like a dictionary that we everyone should have :)
unfortunately it is not writen by Chinese...
however,I still have a question that if the text mode address-0xb8000 can be changed,why 0xb8000,not others?
and I have ever seen that someone using 15h(belongs to BIOS functions) to set and get IVT addresses...
Title: Re: how to change as86 assember that nasm needed
Post by: codeferever on September 27, 2010, 12:56:46 PM
and when I was trying to achieve the routine with c language,the VC compiler said "the memory can not be writen!",why?
here's my c code:
Code: [Select]
#include<stdio.h>
int main()
{
int count=100;
unsigned char *p;
p=0xb800+5*80+4;
while(count--){
*p='a';
p++;
}
return 0;
}
Title: Re: how to change as86 assember that nasm needed
Post by: Frank Kotler on September 27, 2010, 08:27:49 PM
Dunno. Perhaps the VC compiler thinks Bill Gates owns your machine?

Best,
Frank

Title: Re: how to change as86 assember that nasm needed
Post by: cm on September 27, 2010, 10:58:01 PM
Try accessing memory at 0B8000h or 0B800h in gcc Frank ;D

BTW, although that might not be your problem, your code accessed "0xb800+5*80+4" which is wrong because you need "5*80+4" in the segment 0xb800. Maybe "0xb8000+5*80+4" would be better, but maybe you need some specific syntax to specify the segment. (Also make sure to actually use a DOS compiler. Protected mode operating systems don't have such a buffer at this address.)
Title: Re: how to change as86 assember that nasm needed
Post by: Frank Kotler on September 27, 2010, 11:29:18 PM
"Try accessing memory at 0B8000h or 0B800h in gcc Frank Grin"

But why? I'd open /dev/vcsa or so, if I wanted to do it in gcc - or even if I didn't...

As you suggest, you'll want a 16-bit compiler, and don't they have a "make far pointer" command, of some sort?

Best,
Frank

Title: Re: how to change as86 assember that nasm needed
Post by: cm on September 28, 2010, 01:27:52 PM
But why? I'd open /dev/vcsa or so, if I wanted to do it in gcc - or even if I didn't...

There are probably ways to do this in a win32 program too. The point was that setting pointers to arcane values is not the way to go in most protected mode environments.
Title: Re: how to change as86 assember that nasm needed
Post by: Frank Kotler on September 29, 2010, 01:03:39 AM
Right. Instead of trying to make a stupid joke, I should have tried to explain why, in a protected mode OS, just writing to 0xb8000 isn't likely to do anything useful. In a word "paging"... "virtual memory"... or, "when is 0xb8000 not 0xb8000". A Linux executable starts at 0x8048000. Another Linux executable starts at 0x8048000, too. (same idea in Windows, only the address is 0x400000... or so) Yet we can run them at the same time! How is this possible? These addresses are "virtual" addresses, and don't refer directly to physical RAM. Instead, they serve as a sort of "index" into a hierarchy of "page directories" and "page tables"... These eventually refer to physical RAM... or perhaps to a swap file, if we're out of RAM (we don't want this to happen!) I'm fuzzy on the details, but you'll need to know if you're writing an OS!

The video (text) memory is at 0xB8000 physical. But in a multi-tasking OS, we wouldn't want to write direct to video memory even if we could - it might not be "our turn". So we pretty much need to utilize the OS for this kind of thing...

Right now, Codeferever (and maybe Maryjane, too - apparently they're not classmates) kind of have one foot in each of three canoes. :) We started out looking at Linux 0.12, and its "bootsect.s" - used the bios to print its message. Then we looked at some "dos" code, writing to 0xb800:0000 (and following bytes). This is, no doubt, running in "fake dos", as provided by Windows (ntdvm.dll?). You may need to need to be in "full screen mode" for this to work, it might not work in a "dos Window". Then we look at VC code. I don't know VC, but I ASSume it expects to be producing "Windows programs". Same CPU, but very different sets of rules, in terms of what we're allowed to do, and what has been done for us!

You'll gain an appreciation of this as you work from "bootsect.s" up through loading a working "system" of some kind. A 16-bit system is mildly amusing, but not useful, so you'll want to get into protected mode... set of tutorials by Alexei Frounze you may find useful here:

http://members.tripod.com/protected_mode/alexfru/pmtuts.html

Much more info about OS development here:

http://wiki.osdev.org/Main_Page

I suppose if 16-bit systems are obsolete, 32-bit systems are well on their way...

http://wiki.osdev.org/User:Stephanvanschaik/Setting_Up_Long_Mode

That should keep you busy for quite a long time! But take it in small steps, and we'll see if we can help with assembly-related questions that come up (if any). :)

Best,
Frank

Title: Re: how to change as86 assember that nasm needed
Post by: codeferever on September 29, 2010, 06:14:40 AM
Thank you,Frank!
I know,each OS has it's own memory map,and DOS set text-mode at 0xb8000,and windows put it at 0x40000,perhaps,although in a virtual DOS(I want to know the range of DOS in Windows XP,if anyone know).And when we use nasm to compile a 16-bit code,windows will set it's start code at "Virtual DOS"address,then we can display our routine correctly,right?
and if we use VC,it will set it at a address(this is what I want to know,but  I think it is not the "Virtual DOS"address...) by default , however,my code will run into a "can't be read or write" space,then windows warning us ?

I want to know the DOS memory map,is there anybody knows?
And I think it is a very interesting way to control a peripheral device like writing characters at 0xb8000 when their addresses have been known in Virtual DOS memory...

Title: Re: how to change as86 assember that nasm needed
Post by: Keith Kanios on September 29, 2010, 03:47:40 PM
x86 Memory Map @ OSDev.org Wiki (http://wiki.osdev.org/Memory_Map_%28x86%29)
Title: Re: how to change as86 assember that nasm needed
Post by: Frank Kotler on September 29, 2010, 06:01:44 PM
Yeah, that's a good one! I was going to suggest that there's a "memory.lst" in that big package of stuff you downloaded from Ralf Brown. The OSdev stuff is probably "more relevant" to what you'll be doing - same information, pretty much.

But I didn't explain it right. Dos doesn't "put" text-mode video memory at 0xB8000, that's where it "is" - physical memory, on the video card. Starts at 0xA0000 - graphics memory, usually. At 0xB0000 is usually "monochrome card" text memory, at 0xB8000 EGA/CGA/VGA text memory. You can persuade the card to use any of these addresses by diddling a couple bits on a port (3CFh ?) - I don't see any advantage to doing so. ("Richard Cooper", a.k.a. "PJ", author of "softer" for Linux, puts text at 0xA0000 - I don't know why. That's how I happen to know we can do it.) At 0xC0000 is the code for the video card

When Windows boots, along with switching to pmode, it enables "paging" (bit 31 in cr0). At this point, all addresses are "virtual". The "virtual dos address" will start at zero and run up to one megabyte (Or so... there's a "high memory area" above one megabyte). But this is "mapped" to physical memory - wherever Windows wants to put it.

This is a hardware feature (available on 386+ dunno about 286) that the OS takes advantage of. You don't "have" to enable paging in your OS - probably want to get something working without it first - but the reason Intel added it, and everybody uses it, is that there are big advantages to "virtual memory".

That's still not a good explanation. Poke around that OSdev site (and nntp:alt.os.development ) looking for "MMU", "paging", "virtual memory" and the like. I suspect that working through an example (which I have not done) is the best way to understand it...

Best,
Frank