Author Topic: how to change as86 assember that nasm needed  (Read 42713 times)

Offline codeferever

  • Jr. Member
  • *
  • Posts: 21
how to change as86 assember that nasm needed
« 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:

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how to change as86 assember that nasm needed
« Reply #1 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


Offline codeferever

  • Jr. Member
  • *
  • Posts: 21
Re: how to change as86 assember that nasm needed
« Reply #2 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!

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how to change as86 assember that nasm needed
« Reply #3 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


Offline codeferever

  • Jr. Member
  • *
  • Posts: 21
Re: how to change as86 assember that nasm needed
« Reply #4 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!


Offline codeferever

  • Jr. Member
  • *
  • Posts: 21
Re: how to change as86 assember that nasm needed
« Reply #5 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$"

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how to change as86 assember that nasm needed
« Reply #6 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


Offline Maryjane

  • New Member
  • Posts: 1
Re: how to change as86 assember that nasm needed
« Reply #7 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   viec lam

Offline codeferever

  • Jr. Member
  • *
  • Posts: 21
Re: how to change as86 assember that nasm needed
« Reply #8 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?










Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how to change as86 assember that nasm needed
« Reply #9 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


Offline codeferever

  • Jr. Member
  • *
  • Posts: 21
Re: how to change as86 assember that nasm needed
« Reply #10 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...

Offline codeferever

  • Jr. Member
  • *
  • Posts: 21
Re: how to change as86 assember that nasm needed
« Reply #11 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;
}

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how to change as86 assember that nasm needed
« Reply #12 on: September 27, 2010, 08:27:49 PM »
Dunno. Perhaps the VC compiler thinks Bill Gates owns your machine?

Best,
Frank


Offline cm

  • Jr. Member
  • *
  • Posts: 65
Re: how to change as86 assember that nasm needed
« Reply #13 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.)
C. Masloch

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how to change as86 assember that nasm needed
« Reply #14 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