i have been studing on how to make a stand alone os written in assembly. i tryed to experiment with it last night. for those that dont know a bootable os has to have AAFF im not sure if its that order, it may be FFAA but it is expected at the 510 - 512 byte of the first sector of the drive. i assembled my file using the command ml /c 16.asm and when i used a hex editor to view the file to make sure it was assembled currectly the file contained the file header, and was padded with 0's till byte 514 which there was the first command.
my questons
using masm is there a way around the above problem?
is there a better assembler to use to make a stand alone operating system?
has an OS ever been written using masm?
Place this at the very end of your code.
Org 07DFEh
BootSig db 055h, 0AAh ;AA55 boot record signature
- or -
BootSig dw 0AA55h ;AA55 boot record signature
Write a macro to pad to the signature. I going to guess, that you will find it difficult to code a boot loader to fit this sector.
Have fun !!!
Regards, P1 :8)
ninjarider,
The EXE header is added by the linker. You can avoid this by specifying the /tiny switch for the (16-bit) linker:
ML /c bootcode.asm
pause
LINK16 /tiny bootcode.obj,bootcode.bin;
pause
The executable file can have any extension. The linker will issue a warning if the start address is not set to 100h.
I would use MASM for this, but I think many/most coders would use some other assembler.
also. how do u declare variables in 16 -bit assembly using masm
i tried something like this
.data
temp db "a", 0
.code
but it keeps giving me an error.
how do i go about setting the start address to 100h
BIOSes of most computers is going to load your code from a storage device to 0:7c00 in memory and far jump to it.
So trying to force it to org 100 is a waste of time, provided your not going to re-write BIOS of your motherboard while your at it. :wink
BTW, org 100 is in the IVT of the uP, not a recommended starting point.
Regards, P1 :8)
ninjarider,
The BIOS will load the boot sector at address 0000:7C00, so you probably should set the location counter to 7C00h at the start of the code segment with "org 7C00h". This will cause the linker to issue a warning, so I mentioned the warning so you would not mistake it for an error.
<start of segment>
org 7C00h
entrypoint: ; Execution will start here
<code and data goes here, 510 bytes max>
org 7DFEh ; 7C00h + 510
<bootsignature>
<end of segment>
would i have to setup any of th stack pointers or other related registers and what would be the best things to set them to
ninjarider,
You need to help yourself some here. Read up some more on the available material on the internet.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcedsn40/html/cgconx86biosbootloader.asp
http://www.nondot.org/~sabre/os/articles
Regards, P1 :8)
ninjarider,
The only registers that will be set for you will be CS and IP. If your code uses the stack, then you will need to set up a stack by loading appropriate values into SS and SP. In addition to the links that P1 provided, you could try searching the old forum:
http://www.old.masmforum.com
ok. looks like i have enough info to read for now.
ninjarider,
You have been here for a while, so I will ask about your thoughts on this.
BootRoot is a project presented at Black Hat USA 2005 by researchers Derek Soeder and Ryan Permeh, as an exploration of technology that custom boot sector code can use to subvert the Windows kernel as it loads. The BootRootKit is a boot sector-based NDIS backdoor that demonstrates the implementation of this technology.
Interest in old boot code, got me curious. So is this your interest in old boot code?
Regards, P1 :8)
well i dont know if i will do anything with windows. i was just interested in bootcode because i have a person goal of making a robot. i would like to get it to the point were i can load my old laptop with all the software for the robot and plug the lpt port into the robot and execute commands. i dont have a specific goal for the robot at this time. just getting it to move would be a breakthrew.
Quote from: P1 on September 09, 2005, 05:44:06 PM
ninjarider,
You have been here for a while, so I will ask about your thoughts on this.
BootRoot is a project presented at Black Hat USA 2005 by researchers Derek Soeder and Ryan Permeh, as an exploration of technology that custom boot sector code can use to subvert the Windows kernel as it loads. The BootRootKit is a boot sector-based NDIS backdoor that demonstrates the implementation of this technology.
Interest in old boot code, got me curious. So is this your interest in old boot code?
Regards, P1 :8)
to make sure i understand your post currectly.
subvert - to undermine
i dont like windows.
what it the interrupt to allow a 16-bit program to return to dos.
ninjarider,
Thanks for your reply !!!
You don't necessarily need to boot a custom OS to play with Robot Code or AI control of objects. You would be writing a lot of overhead support code for program support, that frankly, would distract you from your real goals.
My suggestion would be start with MSDOS/W95/W98 boot disk and replace command.com with your robot program. You get the benefit of a self booting DOS disk with your program automatically loading.
Even then, I know the re-booting is going to get old. And you will look for other more traditional code support for your ideas.
Regards, P1 :8)
Fast exit = INT 20h
Exit with a reason code
MOV AL, YourExitCode
MOV AH, 4Ch
INT 21h
Regards, P1 :8)
y did u ask that about about subverting windows? do u agree or disagree with people of those views?
Quote from: ninjarider on September 09, 2005, 07:42:09 PM
y did u ask that about about subverting windows?
I was interested in your need to get some experince in boot code. I was hoping it was not to build a boot root kit. Like the example I quoted. We are having this discussion because I was sure you were not doing that, otherwise I would have locked this topic and asked you to PM me. But for those that will read this and be alert to that we know that some new member will try this and get shot down before it gets very far.
Quote from: ninjarider on September 09, 2005, 07:42:09 PM
do u agree or disagree with people of those views?
I agree, that it is possible. I agree, that it will in the near future become a serious security threat. A round of boot sector viruses will be renewed. With a new level of technology to hide from the AV's that run in the OSes that they protect. The social engineering will be propagated on copied/shared CDs from system to system with traditional techniques as well.
Regards, P1 :8)
is there any way using masm to assemble files while the computer is in dos mode, no windows overhead.
(edit)
also
im trying to access a byte in memory at address 0040h:0017:
its suppose to be the keyboard status byte.
i've tried using this
mov ds, 0040h
mov di, 0017h
mov dl, ds:di
i've also tried using
mov dl, byte ptr[ds:di]
with either or masm complains about improper use of registers
Quote from: ninjarider on September 12, 2005, 03:09:30 PM
is there any way using masm to assemble files while the computer is in dos mode, no windows overhead.
The old way, we did MASM. Did you make a set of batch files using link16 or link563, depending on who was giving you advise? They should work in DOS mode just fine. How familar are you with DOS bath files? What are you using as a line Editor in DOS mode?
Quote from: ninjarider on September 12, 2005, 03:09:30 PM
im trying to access a byte in memory at address 0040h:0017:
Should be:
mov ax, 040h
mov ds, ax
mov al, ds:[017h] ;DS override
Regards, P1 :8)
Microsoft(R) Windows 98
(C)Copyright Microsoft Corp 1981- 1999.
C:\WINDOWS>cd\masm32
C:\MASM32>bin\ml /c 16.asm
This program cannot be run in DOS mode.
C:\MASM32>bin\link16 /tiny 16.obj
This program requires DOSXNT.EXE to be in your path
thats exactly what does does.
yes i am using link16. and i am using a batch file. my dos is a little rusty.
(edit)
not sure if my code is currect
mov ax, 0040h
mov ds, ax
mov di, 0017h
mov cl, ds:[di]
cmp cl, 0 -- compare to see if register = 0
mov dl, "0"
push cx
mov ah, 06h
int 21h
pop cx
cmp cl, 1 -- check to see if bit one is set
mov dl, "1"
push cx
mov ah, 06h
int 21h
> is there any way using masm to assemble files while the computer is in dos mode, no windows overhead.
http://www.masmforum.com/simple/index.php?topic=2269.0
mov cx, 080h
mov dl, "0"
and cx, 070h
jne lbl1
mov dl, "1"
lbl1:
mov ah, 06h
int 21h
int 20h
is there a problem with this code that i dont see.
for some reason my computer still seems to print 1
JNE = JNZ
80h AND 70h = 0
If you want the jump condition to be a result of zero, you should use JZ.
when accessing memory using segment: offset. is there a way to include a multiplier. or is that c / c++ that im thinking about.
something like ds : [di*4]
maybe im trying to learn to many programming languages
Quote from: ninjarider on September 14, 2005, 02:30:10 PM
when accessing memory using segment: offset. is there a way to include a multiplier. or is that c / c++ that im thinking about.
something like ds : [di*4]
maybe im trying to learn to many programming languages
MOVS - Move String (Byte or Word)
Usage: MOVS dest,src
MOVSB
MOVSW
MOVSD (386+)
Modifies flags: None
Copies data from addressed by DS:SI (even if operands are given) to
the location ES:DI destination and updates SI and DI based on the
size of the operand or instruction used. SI and DI are incremented
when the Direction Flag is cleared and decremented when the Direction
Flag is Set. Use with REP prefixes.
Clocks Size
Operands 808x 286 386 486 Bytes
dest,src 18 5 7 7 1 (W88=26)
A4 MOVS m8, m8 Move byte at address DS:(E)SI to address ES:(E)DI
A5 MOVS m16, m16 Move word at address DS:(E)SI to address ES:(E)DI
A5 MOVS m32, m32 Move doubleword at address DS:(E)SI to address ES:(E)DI
A4 MOVSB Move byte at address DS:(E)SI to address ES:(E)DI
A5 MOVSW Move word at address DS:(E)SI to address ES:(E)DI
A5 MOVSD Move doubleword at address DS:(E)SI to address ES:(E)DIIt appears to me your moving data.
Note: How SI/DI are incremented for you depending on the direction flag.
You may want to review assembly techniques from Art of Assembly by Randall Hyde.
http://webster.cs.ucr.edu/
Regards, P1 :8)
DOSSEG
.386
.MODEL SMALL
.STACK 200h
.code
org 07c00h
START:
jmp Begin
BD_OEMNAME DB "SMITH"
BS_BYTESPERSEC DW 512
BPB_SECPERCLUS DB 1
BPB_RSVDSECCNT DW 1
BPB_NUMFATS DB 2
BPB_ROOTENTCHT DW 224
BPB_TOTSEC16 DW 2880
BPB_MEDIAID DB 0F0H
BPB_FATSZ16 DW 9
BPB_SECPERTRK DW 18
BPB_NUMHEADS DW 2
BPB_HIDDSEC DD 0
BPB_TOTSEC32 DD 0
(the above was an atempt to keep the floppy compatable with windows but a tragic failure)
Begin:
xor ax, ax
mov ds, ax
mov es, ax
PrintStr:
mov esi, offset TEXT
mov ah, 0eh
StrLoop:
lodsb
test al, al
jz Begin
int 10h
jmp strloop
... a bunch of padding..
TEXT db "Tommy Smith", 10, 13, 0
BootSig dw 0aa55h
END START:
considering im using link16 and that for the most part everything else is 16bit code. y would ml and link16 (not sure which is to blame) would requir the esi instead of the si.
is there any explaination for this.
(edit) added all the code (/edit)
The code you posted is not complete so it is impossible to know exactly what you are doing. ESI would be required if the segment word size were set to USE32, in which case offset addresses would be 32-bit values instead of the 16-bit values that are normal for 16-bit code. The most likely cause of this would be that you placed a .386 or higher processor directive before the .MODEL directive instead of after it.
See "Setting Segment Word Sizes (80386/486 Only)" here:
http://webster.cs.ucr.edu/Page_TechDocs/MASMDoc/ProgrammersGuide/Chap_02.htm
START:
xor ax, ax
int 16h - i might have the wrong interrupt but get keycode from keyboard
cmp al, 13
je Commandline
mov Letter, al
jmp START
Commandline
mov ah, 0eh
int 10h
mov al, 10
int 10h
jmp START
Letter db 0
the above code is suppose to get the keys pressed from the keyboard
if enter key is pressed then jump to CommandLine
and save the last key pressed
for some reason this code doesn't do what i expect it to do.
It's not clear to me what you are trying to do, but your calls to Interrupt 10h are not correct.
From Ralf Brown's Interrupt List:
INT 10 - VIDEO - TELETYPE OUTPUT
AH = 0Eh
AL = character to write
BH = page number
BL = foreground color (graphics modes only)
Return: nothing
Desc: display a character on the screen, advancing the cursor and scrolling
the screen as necessary
Notes: characters 07h (BEL), 08h (BS), 0Ah (LF), and 0Dh (CR) are interpreted
and do the expected things
An on-line HTML version of the Interrupt List is available here:
http://www.ctyme.com/rbrown.htm
i can uderstand what your saying about the interuppt not looking right but theres a line i left out. concidering the laptop that has the code is at home and im at the office. anyways, its not the interrupts that im having a problem with its the cmp al, 13 and the je statments.
if i replace the cmp al, 13 and the je with xor al, 13 and je it will work like i expect. but the cmp statment wont. im not sure if its my hardware or what.
You should get the same result for both. If AL=13 then CMP AL,13 and XOR AL,13 will both set the zero flag, so the jump will be taken.
well for some reason it wont take the jump. i dont know y. i'll disassemble it later to see if its compiling correct.
ok really wierd.
using .386
mov ah, 0eh
mov al, 41h
int 10h
displays the letter A
mov ax, 0e41h
int 10h
does absolutly nothing, even keeps my floppy running untill i reboot into windows.
mov ax, 0e41h
mov ax, 0e41h
int 10h
or
mov ax, 0e41h
int 10h
int 10h
either or works. displays A
mov ax, 0e41h
nop
int 10h
gets the bios stuck in a loop filling the screen with "^A"
is my computer stupid?????
Yes. When I was developing my OS I got really annoyed at that. mov ax does not work but if you do ah and al separately it works.
thnx now i atleast know its not me. helps keep the sanity
ninjarider,
With 16-bit segments the code you posted works normally. I think the problem is that you are specifying 32-bit segments, probably by placing the .386 directive above the model directive. Again, see "Setting Segment Word Sizes (80386/486 Only)" here:
http://webster.cs.ucr.edu/Page_TechDocs/MASMDoc/ProgrammersGuide/Chap_02.htm
I can't test this right now, but I suspect that under DOS this code would behave normally. IOW I suspect that the problem here is in the way Windows handles the code. Under Windows 2000 I can correct the problem by substituting EAX for AX. You should expect problems calling BIOS functions that take address arguments from a segment where the default address size is 32 bits.
well the thing is that im not dealing with windows or dos. most of this topic is my adventures into writing an operating system just so i could say i did it. from the interrupt list that i have the bios uses 16-bit segments but the os i was coding used 32-bit just so that i dont have to deal with the 64k limit. even if it was the segment size that wouldn't explain y if the statements are doubled that it works which is y i posted the question the way i did. i'll read you link thou. might prove of use somewere else.
Quotewell the thing is that im not dealing with windows or dos
But you are running your code under Windows, and describing problems that you are having under Windows. I was trying to point out that the problem, at least with the AX versus AH/AL thing, might be Windows.
Quotei was coding used 32-bit just so that i dont have to deal with the 64k limit
Using 32-bit segments will not, in itself, change the 64KB limit. To change the 64KB limit you must change the segment limits that the processor is using, and to do that you must switch to protected-mode, at least temporarily.
> even if it was the segment size that wouldn't explain y if the statements are doubled
It is not the segment size. with the directive .386 you are telling MASM that it should generate code for a "32bit code segment". Such code usually can only be executed in protected mode, something which isn't true for your boot loader code.
And then, why does it work somehow?
Your code (32bit code):
mov ax, 0e41h ;66 B8 41 0E
int 10h ;CD 10
int 10h ;CD 10
if this code is executed in real-mode the cpu will "interpret" the opcodes as:
mov eax, 10CD0E41h ;66 B8 41 0E CD 10
int 10h ;CD 10
thus it works (HIWORD of EAX is ignored by this interrupt), but just by chance!
MichaelW,
my appolagies. maybe in the begining i should have mention the way i test and assemble my code. while in windows i edit the code and when i think im done adding code for the moment i assemble it and run debug from the command prompt which then writes the boot sector on the floppy disk. then using the old ctrl+alt+del restart the computer loading my boot code. so there is no windows/dos bullshit to deal with.
gustav,
hmmmm.... interesting.
ok. so i cant initially use 32-bit code for a boot loader. (weres that intell architecture manual.) from what i read theres not many advantages to protected mode besides the restriction to programs. so hummm... damn computer.
One disadvantage of protected mode is that you cannot reasonably utilize the BIOS functions. A viable alternative is big-real mode, aka unreal mode, which can allow you to use 32-bit addresses and the BIOS functions, other than those that switch to protected mode. Basically, to enter big-real mode you switch to protected mode, load segment descriptors with suitable segment limit values into the descriptor caches (by loading the segment registers), and switch back to real mode. Thereafter, values loaded into the segment registers (in real mode only) will change the segment base, but not the segment limit.
Just keep in mind what kind of code you're generating.
When used at the very beginning of your source code (before .model), the .386 directive does two (not just one!) things. Not only does it allow you to use the extra 80386 instructions in your source code, but it also changes the default segment type to USE32. And the problem is that you don't want to use code from a USE32 segment accessing data in a USE32 segment as your boot code.
One of the correct methods is to put .model (fixing the default segment type to USE16) before .386.
Under DEBUG, you can use the unassemble (U) command to see what kind of code the processor will execute in real mode.
=====
To get an idea of what may be happening, let's start with code that is assembled in a USE32 code segment BY MISTAKE.
66 89 CB mov bx,cx
Notice the operand size prefix code 66. To get the exact same binary code in a USE16 code segment, you write
66 89 CB mov ebx,ecx
When you boot up, the processor itself is a full 386, Pentium or whatever and can execute this code, but assumes the code was assembled as USE16 code. If you wanted to leave the upper 16 bits of EBX unchanged, it won't happen.
You also get nasty effects where the processor uses 32-bit immediate data when you expected it to use 16-bit immediate data, effectively swallowing up instructions as Gustav illustrated. Or worse, the processor uses 16-bit addresses when 32-bit addresses were generated, adding two bytes of instruction code into the execution stream.
thnx