How to make a real stand-alone system?

Discussions on more advanced topics such as monolithic vs micro-kernels, transactional memory models, and paging vs segmentation should go here. Use this forum to expand and improve the wiki!
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: How to make a real stand-alone system?

Post by Brendan »

Hi,
dozniak wrote:
m12 wrote:ndisasm -b [16, 32, 64] file > out.lst
You do realise that you've posted mostly wrong crap? Not everything in the bootsector is code, x86 assembly might look totally different if you accidentally start disassembling at the wrong offset.
Doing it right (e.g. following every call or jmp to determine what is/isn't executed) is a massive pain in the neck - I should know:

Code: Select all

00007C00  EB64              jmp short 0x7c66

00007C00        90 42 77 74 53 65  63 4f 53 76 62 72 29 7c  |  .BwtSecOSvbr)||
00007C10  10 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00007C20  00 00 00 00 00 00 00 00  00 00 7e 00 01 02 11 00  |..........~.....|
00007C30  a0 01 01 01 12 00 c4 00  02 01 12 00 e8 01 02 01  |................|
00007C40  0c ff                                             |..              |

00007C42  E464              in al,0x64
00007C44  2401              and al,0x1
00007C46  7506              jnz 0x7c4e
00007C48  33C9              xor cx,cx
00007C4A  E2FE              loop 0x7c4a
00007C4C  EBF4              jmp short 0x7c42
00007C4E  B501              mov ch,0x1
00007C50  E2FE              loop 0x7c50
00007C52  E460              in al,0x60
00007C54  CB                retf

00007C55  BFC27C            mov di,0x7cc2
00007C58  FE05              inc byte [di]
00007C5A  FB                sti
00007C5B  57                push di
00007C5C  9A687C0000        call word 0x0:0x7c68
00007C61  5F                pop di
00007C62  FE0D              dec byte [di]
00007C64  FA                cli
00007C65  C3                ret

00007C66  EB6A              jmp short 0x7cd2

00007C68  A10E7C            mov ax,[0x7c0e]
00007C6B  96                xchg ax,si
00007C6C  AC                lodsb
00007C6D  3CFF              cmp al,0xff
00007C6F  7201              jc 0x7c72
00007C71  CB                retf
00007C72  8AE0              mov ah,al
00007C74  B000              mov al,0x0
00007C76  A3167C            mov [0x7c16],ax
00007C79  8EC0              mov es,ax
00007C7B  8A4401            mov al,[si+0x1]
00007C7E  6633C9            xor ecx,ecx
00007C81  3C00              cmp al,0x0
00007C83  7402              jz 0x7c87
00007C85  B112              mov cl,0x12
00007C87  33C0              xor ax,ax
00007C89  8A4403            mov al,[si+0x3]
00007C8C  03C8              add cx,ax
00007C8E  8A4402            mov al,[si+0x2]
00007C91  8BD0              mov dx,ax
00007C93  B224              mov dl,0x24
00007C95  F7E2              mul dx
00007C97  03C8              add cx,ax
00007C99  66A1207C          mov eax,[0x7c20]
00007C9D  6603C8            add ecx,eax
00007CA0  6649              dec ecx
00007CA2  66890E187C        mov [0x7c18],ecx
00007CA7  AC                lodsb
00007CA8  8AE0              mov ah,al
00007CAA  B000              mov al,0x0
00007CAC  A3147C            mov [0x7c14],ax
00007CAF  93                xchg ax,bx
00007CB0  AC                lodsb
00007CB1  8AE0              mov ah,al
00007CB3  A0287C            mov al,[0x7c28]
00007CB6  92                xchg ax,dx
00007CB7  AC                lodsb
00007CB8  50                push ax
00007CB9  8AE0              mov ah,al
00007CBB  AC                lodsb
00007CBC  91                xchg ax,cx
00007CBD  AC                lodsb
00007CBE  A2127C            mov [0x7c12],al
00007CC1  B402              mov ah,0x2
00007CC3  60                pushaw
00007CC4  BE107C            mov si,0x7c10
00007CC7  CD13              int 0x13
00007CC9  7227              jc 0x7cf2
00007CCB  61                popaw
00007CCC  58                pop ax
00007CCD  E80400            call word 0x7cd4
00007CD0  EB9A              jmp short 0x7c6c

00007CD2  EB2A              jmp short 0x7cfe

00007CD4  56                push si
00007CD5  91                xchg ax,cx
00007CD6  33C0              xor ax,ax
00007CD8  8ED8              mov ds,ax
00007CDA  BF008F            mov di,0x8f00
00007CDD  B800B0            mov ax,0xb000
00007CE0  8EC0              mov es,ax
00007CE2  91                xchg ax,cx
00007CE3  0430              add al,0x30
00007CE5  AA                stosb
00007CE6  5E                pop si
00007CE7  C3                ret

00007CE8  50                push ax
00007CE9  E460              in al,0x60
00007CEB  3C01              cmp al,0x1
00007CED  58                pop ax
00007CEE  7407              jz 0x7cf7
00007CF0  EBD1              jmp short 0x7cc3
00007CF2  3C00              cmp al,0x0
00007CF4  61                popaw
00007CF5  74F1              jz 0x7ce8
00007CF7  58                pop ax
00007CF8  B0CE              mov al,0xce
00007CFA  EBD1              jmp short 0x7ccd

00007CF0                                       00 7e        |            .~  |


00007CFE  33C0              xor ax,ax
00007D00  8ED8              mov ds,ax
00007D02  8ED0              mov ss,ax
00007D04  BC007C            mov sp,0x7c00
00007D07  92                xchg ax,dx
00007D08  A2287C            mov [0x7c28],al
00007D0B  3C00              cmp al,0x0
00007D0D  7405              jz 0x7d14
00007D0F  B042              mov al,0x42
00007D11  A2C27C            mov [0x7cc2],al
00007D14  BE107C            mov si,0x7c10
00007D17  1E                push ds
00007D18  9A687C0000        call word 0x0:0x7c68
00007D1D  1F                pop ds
00007D1E  FA                cli
00007D1F  A1007E            mov ax,[0x7e00]
00007D22  3C90              cmp al,0x90
00007D24  7503              jnz 0x7d29
00007D26  E8D700            call word 0x7e00
00007D29  B800B0            mov ax,0xb000
00007D2C  8EC0              mov es,ax
00007D2E  9A427C0000        call word 0x0:0x7c42
00007D33  3C41              cmp al,0x41
00007D35  74EF              jz 0x7d26
00007D37  3C3F              cmp al,0x3f
00007D39  7507              jnz 0x7d42
00007D3B  1E                push ds
00007D3C  E816FF            call word 0x7c55
00007D3F  1F                pop ds
00007D40  EBE7              jmp short 0x7d29
00007D42  BEFC7C            mov si,0x7cfc
00007D45  8BDE              mov bx,si
00007D47  3C4D              cmp al,0x4d
00007D49  7504              jnz 0x7d4f
00007D4B  FF04              inc word [si]
00007D4D  EB06              jmp short 0x7d55
00007D4F  3C4B              cmp al,0x4b
00007D51  7504              jnz 0x7d57
00007D53  FF0C              dec word [si]
00007D55  EB08              jmp short 0x7d5f
00007D57  3C2D              cmp al,0x2d
00007D59  7506              jnz 0x7d61
00007D5B  AD                lodsw
00007D5C  96                xchg ax,si
00007D5D  FE04              inc byte [si]
00007D5F  EB08              jmp short 0x7d69
00007D61  3C2C              cmp al,0x2c
00007D63  7506              jnz 0x7d6b
00007D65  AD                lodsw
00007D66  96                xchg ax,si
00007D67  FE0C              dec byte [si]
00007D69  EB09              jmp short 0x7d74
00007D6B  3C23              cmp al,0x23
00007D6D  7505              jnz 0x7d74
00007D6F  BF0A7C            mov di,0x7c0a
00007D72  FE05              inc byte [di]
00007D74  90                nop
00007D75  90                nop
00007D76  90                nop
00007D77  8BF3              mov si,bx
00007D79  AD                lodsw
00007D7A  96                xchg ax,si
00007D7B  B8FA00            mov ax,0xfa
00007D7E  BF0080            mov di,0x8000
00007D81  2BF0              sub si,ax
00007D83  B9F401            mov cx,0x1f4
00007D86  B40B              mov ah,0xb
00007D88  A00A7C            mov al,[0x7c0a]
00007D8B  2401              and al,0x1
00007D8D  7543              jnz 0x7dd2
00007D8F  AC                lodsb
00007D90  8AD0              mov dl,al
00007D92  2C64              sub al,0x64
00007D94  720F              jc 0x7da5
00007D96  8AD0              mov dl,al
00007D98  2C64              sub al,0x64
00007D9A  7205              jc 0x7da1
00007D9C  92                xchg ax,dx
00007D9D  B032              mov al,0x32
00007D9F  EB06              jmp short 0x7da7
00007DA1  B031              mov al,0x31
00007DA3  EB02              jmp short 0x7da7
00007DA5  B020              mov al,0x20
00007DA7  AB                stosw
00007DA8  92                xchg ax,dx
00007DA9  BB000B            mov bx,0xb00
00007DAC  3C0A              cmp al,0xa
00007DAE  7205              jc 0x7db5
00007DB0  43                inc bx
00007DB1  2C0A              sub al,0xa
00007DB3  EBF7              jmp short 0x7dac
00007DB5  93                xchg ax,bx
00007DB6  3C00              cmp al,0x0
00007DB8  7507              jnz 0x7dc1
00007DBA  92                xchg ax,dx
00007DBB  3C20              cmp al,0x20
00007DBD  7404              jz 0x7dc3
00007DBF  B000              mov al,0x0
00007DC1  0430              add al,0x30
00007DC3  AB                stosw
00007DC4  93                xchg ax,bx
00007DC5  0430              add al,0x30
00007DC7  AB                stosw
00007DC8  B020              mov al,0x20
00007DCA  AB                stosw
00007DCB  E2C2              loop 0x7d8f
00007DCD  EB22              jmp short 0x7df1

00007DC0                                                b0  |               .|
00007DD0  20                                                |                |

00007DD1  AB                stosw
00007DD2  AC                lodsb
00007DD3  50                push ax
00007DD4  C0E804            shr al,0x4
00007DD7  0430              add al,0x30
00007DD9  3C3A              cmp al,0x3a
00007DDB  7202              jc 0x7ddf
00007DDD  0407              add al,0x7
00007DDF  AB                stosw
00007DE0  58                pop ax
00007DE1  240F              and al,0xf
00007DE3  0430              add al,0x30
00007DE5  3C3A              cmp al,0x3a
00007DE7  7202              jc 0x7deb
00007DE9  0407              add al,0x7
00007DEB  AB                stosw
00007DEC  B020              mov al,0x20
00007DEE  AB                stosw
00007DEF  E2E0              loop 0x7dd1
00007DF1  BFD187            mov di,0x87d1
00007DF4  B00C              mov al,0xc
00007DF6  AA                stosb
00007DF7  47                inc di
00007DF8  AA                stosb
00007DF9  47                inc di
00007DFA  AA                stosb
00007DFB  E930FF            jmp word 0x7d2e

00007DF0                                             55 aa  |              U.|
Now all we need is for someone to add comments, so that it's easy to see how bad this code actually is.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: How to make a real stand-alone system?

Post by Brendan »

Hi,
Brendan wrote:Now all we need is for someone to add comments, so that it's easy to see how bad this code actually is.
Ok, I was bored/curious and started deciphering the code. Here's what I have so far:

Code: Select all

00007C00  EB64              jmp short 0x7c66

00007C00        90 42 77 74 53 65  63 4f 53 76 62 72 29 7c  |  .BwtSecOSvbr)||
00007C10  10 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00007C20  00 00 00 00 00 00 00 00  00 00 7e 00 01 02 11 00  |..........~.....|
00007C30  a0 01 01 01 12 00 c4 00  02 01 12 00 e8 01 02 01  |................|
00007C40  0c ff                                             |..              |

;Get byte from keyboard with race conditions (instead of using the BIOS function that is designed to do this right)

00007C42  E464              in al,0x64               ;al = PS/2 controller status register
00007C44  2401              and al,0x1               ;al = PS/2 controller output buffer status (should be "test al,1")
00007C46  7506              jnz 0x7c4e               ;If BIOS IRQ handler hasn't already got the byte, get the byte
00007C48  33C9              xor cx,cx                ;cx = 0x0000 ready for a broken/idiotic delay
00007C4A  E2FE              loop 0x7c4a              ;Broken/idiotic delay (may take 0 cycles on some CPUs)
00007C4C  EBF4              jmp short 0x7c42         ;Try again
00007C4E  B501              mov ch,0x1               ;ch = 0x1?? ready for a broken/idiotic delay (contents of CL is undefined)
00007C50  E2FE              loop 0x7c50              ;Broken/idiotic delay (may take 0 cycles on some CPUs)
00007C52  E460              in al,0x60               ;al = keyboard data of some sort
00007C54  CB                retf                     ;Pointless "retf" for no reason (should be "ret")

;Retarded self-modifying code to screw up CPU's trace cache instead of using a simple variable

00007C55  BFC27C            mov di,0x7cc2
00007C58  FE05              inc byte [di]            ;Should be "inc byte [0x7CC2]"
00007C5A  FB                sti                      ;Major WTF (there's no sane excuse for IRQs to be disabled by default)
00007C5B  57                push di
00007C5C  9A687C0000        call word 0x0:0x7c68     ;*facepalm* (this is just a silly wrapper around a retarded "swiss army knife" mess)
00007C61  5F                pop di
00007C62  FE0D              dec byte [di]
00007C64  FA                cli                      ;Continuation of major WTF (there's no sane excuse)
00007C65  C3                ret

00007C66  EB6A              jmp short 0x7cd2         ;This is part of a jump that jumps to a jump that jumps to a jump(!)
                                                     ;   should be "jmp near 0x7cfe", or just shift the code at 0x7CFE here
                                                     ;   to avoid the need for pointless JMPs

;Retarded puke to read or write sectors (using BIOS function 0x02, 0x03, 0x42 or 0x43 depending on what was written to 0x7CC2
;by self modifying code, even though BIOS functions 0x02 and 0x03 are extremely different to BIOS functions 0x42 and 0x43 and
;none of the logic is shared). Desperately needs to be replaced by a function pointer (e.g. "call [disk_function]").

;WARNING: This code also uses "lodsb" in a pointless and retarded way instead of doing "mov reg,[address]". This complicates
everything for no sane reason.

00007C68  A10E7C            mov ax,[0x7c0e]          ;ax = 0x7C29
00007C6B  96                xchg ax,si               ;si = 0x7C29, ax = undefined (should be "mov si,[0x7c0e]" or "mov si,0x7C29")
00007C6C  AC                lodsb                    ;WARNING: There's no CLD or STD anywhere, so undefined behaviour here..
                                                     ;al = highest 8-bits of segment
00007C6D  3CFF              cmp al,0xff              ;Is end of list reached?
00007C6F  7201              jb 0x7c72                ; no
00007C71  CB                retf                     ; yes, return with a pointless "RETF" that should be a plain "RET"

00007C72  8AE0              mov ah,al                ;ah = highest 8-bits of segment (should probably be "shl ax,8")
00007C74  B000              mov al,0x0               ;ax = highest 8-bits of segment << 8 (should probably be "shl ax,8")
00007C76  A3167C            mov [0x7c16],ax          ;Store it as high word of "address of buffer" in BIOS int0x13 extensions disk address packet
00007C79  8EC0              mov es,ax                ;es = segment

00007C7B  8A4401            mov al,[si+0x1]          ;al = some sort of flag
00007C7E  6633C9            xor ecx,ecx              ;ecx = 0 (WARNING: assuming 80386 or later)
00007C81  3C00              cmp al,0x0               ;Is some sort of flag zero?
00007C83  7402              jz 0x7c87                ; yes, leave ecx = 0
00007C85  B112              mov cl,0x12              ; no, ecx = 18

00007C87  33C0              xor ax,ax                ;ax = 0 (should be deleted)
00007C89  8A4403            mov al,[si+0x3]          ;al = something (should be deleted)
00007C8C  03C8              add cx,ax                ;cx = something (should be "movzx cx,byte [si+0x3]")
00007C8E  8A4402            mov al,[si+0x2]          ;ax = something (should be "movzx ax,byte [si+0x2]")
00007C91  8BD0              mov dx,ax                ;dx = something (never used, should be deleted)
00007C93  B224              mov dl,0x24              ;dx = 0x0024 (should be "mov dx,0x0024")
00007C95  F7E2              mul dx                   ;dx:ax = something * 0x0024
00007C97  03C8              add cx,ax                ;ecx = something * 0x0024 + something (WARNING: highest 16-bits of multiplication in DX are lost)
00007C99  66A1207C          mov eax,[0x7c20]         ;ax = 0x00000000 (value never modified)
00007C9D  6603C8            add ecx,eax              ;ecx = something * 0x0024 + something + 0x00000000 (pointless, should be deleted)
00007CA0  6649              dec ecx                  ;ecx = something * 0x0024 + something - 1
00007CA2  66890E187C        mov [0x7c18],ecx         ;Store it as low dword of "starting LBA" in BIOS int0x13 extensions disk address packet

00007CA7  AC                lodsb                    ;al = something
00007CA8  8AE0              mov ah,al                ;ah = something (should probably be "shl ax,8")
00007CAA  B000              mov al,0x0               ;ax = something << 8 (should probably be "shl ax,8")
00007CAC  A3147C            mov [0x7c14],ax          ;Store it as low word of "address of buffer" in BIOS int0x13 extensions disk address packet
00007CAF  93                xchg ax,bx               ;bx = something, ax = undefined (should probably be "mov bx,ax")
00007CB0  AC                lodsb                    ;al = something
00007CB1  8AE0              mov ah,al                ;ah = something
00007CB3  A0287C            mov al,[0x7c28]          ;al = something
00007CB6  92                xchg ax,dx               ;dx = something, ax = undefined (should probably be "mov dx,ax")
00007CB7  AC                lodsb                    ;al = cylinder
00007CB8  50                push ax
00007CB9  8AE0              mov ah,al                ;ah = cylinder
00007CBB  AC                lodsb                    ;al = sector
00007CBC  91                xchg ax,cx               ;ch = cylinder, cl = sector, ax = undefined (should probably be "mov cx,ax" or maybe "mov ch,[cylinder]; mov cl,[sector]")
00007CBD  AC                lodsb                    ;al = sectors to read
00007CBE  A2127C            mov [0x7c12],al          ;Store it as low byte of "number of blocks to transfer" in BIOS int0x13 extensions disk address packet
00007CC1  B402              mov ah,0x2               ;WARNING: Value 0x02 is modified by self modifying code
00007CC3  60                pushaw
00007CC4  BE107C            mov si,0x7c10
00007CC7  CD13              int 0x13                 ;Use BIOS function 0x02, 0x03, 0x42 or 0x43
00007CC9  7227              jc 0x7cf2                ;If error, jump to error handler that doesn't do anything to handle the error at all
00007CCB  61                popaw
00007CCC  58                pop ax
00007CCD  E80400            call word 0x7cd4
00007CD0  EB9A              jmp short 0x7c6c
I have no intention of doing more.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: How to make a real stand-alone system?

Post by DavidCooper »

m12 wrote:ndisasm -b [16, 32, 64] file > out.lst
Thanks - I'll try that out with NASM.

What I've done obviously won't assemble without a lot of corrections, but anyone who knows what they're about should be able to fix it. The first proper bit of code to run (other than a series of short jumps to get past various debris fields) is about half way down, where it says "start":-

Code: Select all

; bootsector
00000000  EB64              jmp short 0x66    ;jump to the part labelled ;####
00000002  90                nop



00000003  4277745365634F53  "BwtSecOS"
0000000B  766272            "VBR"



data_table_address

0000000E  297C              (2 bytes)         ;this variable points at a table of load/save data



DAP

00000010  10 (+ 15 zeros)   (16 bytes)        ;structure used for LBA loads and saves



LBA

00000020  0000...           (8 bytes)         ;variable used to store LBA offset on hard/flash drive



drive_number

00000028  00                (1 byte)          ;variable used to store DL.



load_data                                     ;data to set things up for loads or saves

00000029  007E00010211      data (6 bytes)    ;segMSB,addrMSB,head,track,start_sec,no_of_secs
0000002F  00A001010112      data (6 bytes)
00000035  00C400020112      data (6 bytes)
0000003B  00E80102010C      data (6 bytes)
00000041  FF                data (1 byte)     ;end-of-data marker




;The delay loops in the following keyboard reading routine are there to avoid damage to rare
;machines like 486s running on 386 motherboards where aggressive polling can damage ports.
;It may be overkill, but I never take chances with this when interrupts are disabled.


get_key_input

00000042  E464              in 64h            ;read keyboard status register
00000044  2401              and 1             ;isolate bit-0
00000046  7506              jnz 0x4e          ;jump if new input
00000048  33C9              xor cx,cx         ;delay wanted to avoid aggressive polling
0000004A  E2FE              loop 0x4a         ;this instruction calls itself 65535 times
0000004C  EBF4              jmp short 0x42    ;jump back to check status again
0000004E  B501              mov ch,0x1        ;set up another little delay
00000050  E2FE              loop 0x50         ;run this instruction 255 times
00000052  E460              in al,0x60        ;read keyboard data register
00000054  CB                retf




;The code below modifies a byte of program code which is not normally a done thing,
;but in this special case there's never going to be a recongnisable speed penalty.
;In my normal operating system I make the modifications from protected mode.


save ;(used to modify load routine into save routine, then run it, then restore it)

00000055  BFC27C            mov di,0x7cc2         ;line up DI on immed val in code
00000058  FE05              inc byte [di]         ;change read value to write value
0000005A  FB                sti
0000005B  57                push di
0000005C  9A687C0000        call word 0x0:0x7c68  ;call "load_or_save"
00000061  5F                pop di
00000062  FE0D              dec byte [di]         ;restore the original read value
00000064  FA                cli
00000065  C3                ret





;####

00000066  EB6A              jmp short 0xd2        ;jump past load_or_save routine to ;######




load_or_save 

00000068  A10E7C            mov ax,[0x7c0e]       ;get address from datatableaddress
0000006B  96                xchg ax,si
0000006C  AC                lodsb                 ;get first byte of data
0000006D  3CFF              cmp al,0xff           ;compare with end-of-table value
0000006F  7201              jc 0x72               ;jump past the retf if it's smaller
00000071  CB                retf                  ;EXIT POINT

00000072  8AE0              mov ah,al             ;segMSB into AH
00000074  B000              mov al,0x0            ;complete seg val
00000076  A3167C            mov [0x7c16],ax       ;post into DAP for LBA load/save
00000079  8EC0              mov es,ax             ;and put in ES for CHS load/save

0000007B  8A4401            mov al,[si+0x1]       ;fetch head val from data
0000007E  6633C9            xor ecx,ecx           ;ECX=0, to be used to build a total in
00000081  3C00              cmp al,0x0            ;see which head number it is
00000083  7402              jz 0x87
00000085  B112              mov cl,0x12           ;add 18 if head val = 1

00000087  33C0              xor ax,ax             ;ax=0
00000089  8A4403            mov al,[si+0x3]       ;fetch start_sec_no from data
0000008C  03C8              add cx,ax             ;add this to CX

0000008E  8A4402            mov al,[si+0x2]       ;fetch track number from data
00000091  8BD0              mov dx,ax             ;DH=0
00000093  B224              mov dl,0x24           ;DL=36 (sectors per track)
00000095  F7E2              mul dx                ;AX = tracks * 36
00000097  03C8              add cx,ax             ;add result to CX
00000099  66A1207C          mov eax,[0x7c20]      ;fetch LBA offset
0000009D  6603C8            add ecx,eax           ;add this to ECX
000000A0  6649              dec ecx               ;correct for CHS sector 1 being LBA 0
000000A2  66890E187C        mov [0x7c18],ecx      ;post result into DAP
000000A7  AC                lodsb                 ;fetch addrMSB from data
000000A8  8AE0              mov ah,al             ;put in AH
000000AA  B000              mov al,0x0            ;complete the addr
000000AC  A3147C            mov [0x7c14],ax       ;post into DAP
000000AF  93                xchg ax,bx            ;and put in BX for CHS
000000B0  AC                lodsb                 ;fetch head no from data
000000B1  8AE0              mov ah,al             ;put in AH
000000B3  A0287C            mov al,[0x7c28]       ;put drive-number in AL
000000B6  92                xchg ax,dx            ;move into DX
000000B7  AC                lodsb                 ;fetch track no
000000B8  50                push ax               ;put on stack for display later
000000B9  8AE0              mov ah,al             ;move to AH
000000BB  AC                lodsb                 ;fetch start_sec no
000000BC  91                xchg ax,cx            ;put these in CX
000000BD  AC                lodsb                 ;fetch no_of_secs which stays in AL
000000BE  A2127C            mov [0x7c12],al       ;post into DAP

;The 02 part of the B402 that follows is named as "r/w" in my own programming environment
;and it gets modified from other parts of the bootsector code to switch between CHS and LBA
;modes as well as being changed by +1 or -1 to switch the function between read and write:-

000000C1  B402              mov ah,0x2            ;select "read" function (02 becomes 42h for LBA)
000000C3  60                pushaw
000000C4  BE107C            mov si,0x7c10         ;SI pointing at DAP structure
000000C7  CD13              int 0x13              ;call BIOS to load/save
000000C9  7227              jc 0xf2               ;jump to error code if error
000000CB  61                popaw
000000CC  58                pop ax                ;recover track no.
000000CD  E80400            call word 0xd4        ;call "track" to display progress
000000D0  EB9A              jmp short 0x6c        ;jump back to process next group of 6 data bytes




;######

000000D2  EB2A              jmp short 0xfe         ;jump to start



;The code below is really an extension of load_or_save which displays progress by sending a number
;or other symbol to the screen. It also indicates load/save errors.


track

000000D4  56                push si
000000D5  91                xchg ax,cx             ;save track no. in CL
000000D6  33C0              xor ax,ax
000000D8  8ED8              mov ds,ax              ;restore DS to 0
000000DA  BF008F            mov di,0x8f00          ;address of bottom left of screen
000000DD  B800B0            mov ax,0xb000
000000E0  8EC0              mov es,ax              ;set ES for screen
000000E2  91                xchg ax,cx             ;recover track no. from CL
000000E3  0430              add al,0x30            ;add 48 to print number for initial tracks
000000E5  AA                stosb                  ;send to screen
000000E6  5E                pop si
000000E7  C3                ret



;The following is load/save error handling code which needs to be improved, but it worked so well
;with real floppy disks that I never got round to improving it. It still needs a rewrite though as
;it was never intended to stay in the simple form it's in now:-


error_mid ;(not the entry point)

000000E8  50                push ax
000000E9  E460              in al,0x60             ;read key port if error
000000EB  3C01              cmp al,0x1             ;see if Esc key has been pressed
000000ED  58                pop ax
000000EE  7407              jz 0xf7                ;jump to abandon that chunk and do next
000000F0  EBD1              jmp short 0xc3         ;jump to retry failed load/save

error_start ;(this is the entry point)

000000F2  3C00              cmp al,0x0             ;see if no sectors were loaded/saved
000000F4  61                popaw
000000F5  74F1              jz 0xe8                ;jump to error_mid if none were

000000F7  58                pop ax
000000F8  B0CE              mov al,0xce            ;set replacement track-val to display error
000000FA  EBD1              jmp short 0xcd         ;continue regardless of error




editable_byte_address

000000FC  007E              007E                  ;variable holding addr of byte under cursor




start

000000FE  33C0              xor ax,ax             ;AX=0
00000100  8ED8              mov ds,ax
00000102  8ED0              mov ss,ax
00000104  BC007C            mov sp,0x7c00         ;new stack set up below bootsector
00000107  92                xchg ax,dx            ;move DL into al
00000108  A2287C            mov [0x7c28],al       ;save drive no. to the variable "drive_number"
0000010B  3C00              cmp al,0x0            ;see if drive no. looks like floppy disk
0000010D  7405              jz 0x114              ;jump past next five bytes if so
0000010F  B042              mov al,0x42           ;42h is the "read" value for LBA access
00000111  A2C27C            mov [0x7cc2],al       ;post that value into "load_or_save" at "r/w"
00000114  BE107C            mov si,0x7c10         ;line up SI on DAP
00000117  1E                push ds
00000118  9A687C0000        call word 0x0:0x7c68  ;call "load_or_save" to fill 7E00 to FFFF mem from disk
0000011D  1F                pop ds
0000011E  FA                cli

0000011F  A1007E            mov ax,[0x7e00]       ;collect byte at 7E00
00000122  3C90              cmp al,0x90           ;see if it's a nop
00000124  7503              jnz 0x129             ;if not, jump past the following call
00000126  E8D700            call word 0x200       ;near call to the code at 7E00


loopstart

00000129  B800B0            mov ax,0xb000
0000012C  8EC0              mov es,ax             ;set up ES to access screen memory

0000012E  9A427C0000        call word 0x0:0x7c42  ;far call to "get_key_input"

00000133  3C41              cmp al,0x41           ;scancode for F7 key?         
00000135  74EF              jz 0x126              ;if so, jump back to run the near call to 7E00

00000137  3C3F              cmp al,0x3f           ;scancode for F5 key?
00000139  7507              jnz 0x142
0000013B  1E                push ds
0000013C  E816FF            call word 0x55        ;near call to "save" - saves 7E00->FFFF back to disk
0000013F  1F                pop ds
00000140  EBE7              jmp short 0x129       ;back to "loopstart"

00000142  BEFC7C            mov si,0x7cfc         ;SI holds editable_byte_address
00000145  8BDE              mov bx,si             ;and so does bx

00000147  3C4D              cmp al,0x4d           ;scancode for cursor-right key (ignoring its prefix)
00000149  7504              jnz 0x14f
0000014B  FF04              inc word [si]         ;inc editable_byte_address variable
0000014D  EB06              jmp short 0x155

0000014F  3C4B              cmp al,0x4b           ;scancode for cursor-left key
00000151  7504              jnz 0x157
00000153  FF0C              dec word [si]         ;dec editable_byte_address variable
00000155  EB08              jmp short 0x15f

00000157  3C2D              cmp al,0x2d           ;scancode for Z key
00000159  7506              jnz 0x161
0000015B  AD                lodsw                 ;fetch editable_byte_address
0000015C  96                xchg ax,si
0000015D  FE04              inc byte [si]         ;inc editable byte itself
0000015F  EB08              jmp short 0x169

00000161  3C2C              cmp al,0x2c           ;scancode for X key
00000163  7506              jnz 0x16b
00000165  AD                lodsw                 ;fetch editable_byte_address
00000166  96                xchg ax,si
00000167  FE0C              dec byte [si]         ;dec editable byte itself
00000169  EB09              jmp short 0x174

0000016B  3C23              cmp al,0x23           ;scancode for H key
0000016D  7505              jnz 0x174
0000016F  BF0A7C            mov di,0x7c0a
00000172  FE05              inc byte [di]         ;inc an unimportant name byte at top to signal dec/hex mode


patch_call_here

00000174  90                nop                   ;place to patch in a near call to extend funtionality
00000175  90                nop
00000176  90                nop


display_routine

00000177  8BF3              mov si,bx             ;restore editable_byte_address variable address to SI
00000179  AD                lodsw                 ;fetch the editable byte's address out of that variable
0000017A  96                xchg ax,si            ;put it in SI
0000017B  B8FA00            mov ax,0xfa           ;preparation for subtracting 250 from SI
0000017E  BF0080            mov di,0x8000         ;line up DI on start of screen
00000181  2BF0              sub si,ax             ;take 250 from SI (a byte of code could be saved there)
00000183  B9F401            mov cx,0x1f4          ;count value to print 500 bytes to screen
00000186  B40B              mov ah,0xb            ;AH = screen colour value for cyan text
00000188  A00A7C            mov al,[0x7c0a]       ;AL = dec/hex mode marker
0000018B  2401              and al,0x1            ;isolate bit-0
0000018D  7543              jnz 0x1d2             ;jump if in hex mode

  
print_byte_as_decimal                             ;(I suspect this can be done more efficiently)

0000018F  AC                lodsb                 ;fetch a byte to be printed
00000190  8AD0              mov dl,al             ;copy to DL in case <100
00000192  2C64              sub al,0x64           ;sub 100
00000194  720F              jc 0x1a5              ;jump if was <100
00000196  8AD0              mov dl,al             ;copy to DL in case <100 now
00000198  2C64              sub al,0x64           ;sub 100
0000019A  7205              jc 0x1a1              ;jump if was <100
0000019C  92                xchg ax,dx            ;move AL to DL
0000019D  B032              mov al,0x32           ;AL="2"
0000019F  EB06              jmp short 0x1a7

000001A1  B031              mov al,0x31           ;AL="1"
000001A3  EB02              jmp short 0x1a7

000001A5  B020              mov al,0x20           ;AL=" "

000001A7  AB                stosw                 ;send hundreds digit to screen

000001A8  92                xchg ax,dx            ;move remainder into AL and store hundreds val in DL
000001A9  BB000B            mov bx,0xb00          ;count BL=0
000001AC  3C0A              cmp al,0xa            ;compare with 10
000001AE  7205              jc 0x1b5              ;jump if <10
000001B0  43                inc bx                ;inc tens count
000001B1  2C0A              sub al,0xa            ;subtract 10
000001B3  EBF7              jmp short 0x1ac       ;jump back to compare again

000001B5  93                xchg ax,bx            ;move remnant to BL and the count to AL
000001B6  3C00              cmp al,0x0            ;see if tens digit = 0
000001B8  7507              jnz 0x1c1             ;if not, jump to convert and print it

000001BA  92                xchg ax,dx            ;get hundreds val back in AL
000001BB  3C20              cmp al,0x20           ;see if it was a space
000001BD  7404              jz 0x1c3              ;if so, jump to print another space

000001BF  B000              mov al,0x0            ;else give tens value 0

000001C1  0430              add al,0x30           ;convert to ASCII

000001C3  AB                stosw                 ;send tens digit to screen

000001C4  93                xchg ax,bx            ;AL=BL
000001C5  0430              add al,0x30           ;convert to ASCII
000001C7  AB                stosw                 ;send ones digit to screen

000001C8  B020              mov al,0x20
000001CA  AB                stosw                 ;then send a space
000001CB  E2C2              loop 0x18f            ;loop until 500 bytes printed
000001CD  EB22              jmp short 0x1f1       ;jump past hex version


print_byte_as_hex

000001CF  B020              mov al,0x20
000001D1  AB                stosw                 ;write " " to the screen

000001D2  AC                lodsb                 ;fetch a byte to be printed
000001D3  50                push ax
000001D4  C0E804            shr al,0x4            ;get top four bits
000001D7  0430              add al,0x30           ;part-convert to ASCII
000001D9  3C3A              cmp al,0x3a           ;see if job done
000001DB  7202              jc 0x1df
000001DD  0407              add al,0x7            ;complete for >"9" val.s
000001DF  AB                stosw                 ;write digit to screen

000001E0  58                pop ax
000001E1  240F              and al,0xf            ;get lower four bits
000001E3  0430              add al,0x30           ;part-convert to ASCII
000001E5  3C3A              cmp al,0x3a           ;see if job done
000001E7  7202              jc 0x1eb
000001E9  0407              add al,0x7            ;complete for >"9" val.s
000001EB  AB                stosw                 ;write digit to screen

000001EC  B020              mov al,0x20
000001EE  AB                stosw                 ;send " " to screen
000001EF  E2E0              loop 0x1d1            ;loop till 500 bytes done


make_cursor

000001F1  BFD187            mov di,0x87d1         ;screen addr of byte under cursor
000001F4  B00C              mov al,0xc            ;red value for textscreen
000001F6  AA                stosb                 ;send for 100s
000001F7  47                inc di
000001F8  AA                stosb                 ;send for 10s
000001F9  47                inc di
000001FA  AA                stosb                 ;send for units


000001FB  E930FF            jmp word 0x12e        ;jump back to "loopstart"


000001FE  55AA              55AA                  ;boot sig

Code: Select all

; extension
00000000  F5                cmc                  ;changing that to a nop will make the following code run automatically
00000001  EB25              jmp short 0x28       ;spacing used to help navigate visually
00000003  0000...           (37 zero bytes)

;the code below patches a call into the bootsector to run the code further down, thereby enhancing the functionality.

00000028  B8D900            mov ax,0xd900        ;AX holds a jump distance
0000002B  A3757D            mov [0x7d75],ax      ;posted on top of two nops in bootsector
0000002E  B0E8              mov al,0xe8          ;AL holds a near call instruction
00000030  A2747D            mov [0x7d74],al      ;posted on top of a nop in the bootsector
00000033  C3                ret

00000034  0000....          (28 zeros)           ;spacing to aid navigation

00000050  3C48              cmp al,0x48          ;cursor-up scancode?
00000052  7508              jnz 0x5c
00000054  8B04              mov ax,[si]          ;fetch address of byte under cursor
00000056  2D1400            sub ax,0x14          ;subtract 20 from it
00000059  8904              mov [si],ax          ;post modified address back
0000005B  C3                ret

0000005C  3C50              cmp al,0x50          ;cursor-down scancode
0000005E  7508              jnz 0x68
00000060  8B04              mov ax,[si]
00000062  051400            add ax,0x14          ;add 20 to address
00000065  8904              mov [si],ax
00000067  C3                ret

00000068  C3                ret                  ;more functionality can be added here by replacing this ret
[/quote]
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: How to make a real stand-alone system?

Post by DavidCooper »

dozniak wrote:
m12 wrote:ndisasm -b [16, 32, 64] file > out.lst
You do realise that you've posted mostly wrong crap? Not everything in the bootsector is code, x86 assembly might look totally different if you accidentally start disassembling at the wrong offset.

iow: don't do this again.
Don't be too quick to attack: most of it was actually right and it meant that I only had to write in a few replacement bits of mnemonics and delete a few repeated fake instructions where it was mis-interpreting empty space.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
Mikemk
Member
Member
Posts: 409
Joined: Sat Oct 22, 2011 12:27 pm

Re: How to make a real stand-alone system?

Post by Mikemk »

Yes, I realize, I also realize that everybody here is (should be) smart enough to figure out what's code and what's data.
Programming is 80% Math, 20% Grammar, and 10% Creativity <--- Do not make fun of my joke!
If you're new, check this out.
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: How to make a real stand-alone system?

Post by DavidCooper »

Brendan wrote:Hi,
Brendan wrote:Now all we need is for someone to add comments, so that it's easy to see how bad this code actually is.
It isn't ideal, but it's a hell of a lot better than your ludicrous objections suggest. I will comment on every single negative comment you've made. It'll be fun to add up the score in terms of the good ones versus the bad ones:-
;Get byte from keyboard with race conditions (instead of using the BIOS function that is designed to do this right)
Designed only for use with interrupts disabled.
If BIOS IRQ handler hasn't already got the byte...
Not possible with interrupts disabled.
ready for a broken/idiotic delay...Broken/idiotic delay (may take 0 cycles on some CPUs)...ready for a broken/idiotic delay (contents of CL is undefined)
Delays are not idiotic on the rare type of machine these delays are designed to protect, and CX=0 after the loops run out, so the loop instruction decs it to 15535 before comparing with zero on the kind of machine this is intended to protect. You may not think it possible to damage a machine through aggressive polling, but it most certainly can be done.
Broken/idiotic delay (may take 0 cycles on some CPUs)
ditto
00007C54 CB retf ;Pointless "retf" for no reason (should be "ret")
Ignorant fool doesn't recognise that it's easier to call a routine with a far call as you don't have to work out the jump distance. This makes it much easier to develop the OS further.
;Retarded self-modifying code to screw up CPU's trace cache instead of using a simple variable
How much speed do you think matters at this primitive level while calling the BIOS? What I've gained here is more compact code. I'd have thought you'd have understood the need for that here.
Major WTF (there's no sane excuse for IRQs to be disabled by default)
The first thing I did when I wrote my main OS was switch to protected mode, and it was a long time before I bothered with interrupts other than when returning to load/save data. I never bothered to read up on how to get keyboard input from the BIOS as you can't do that from protected mode and I wanted to work in 32-bit mode as much as possible.
*facepalm* (this is just a silly wrapper around a retarded "swiss army knife" mess)
That is a means to load and save data efficiently through the BIOS in CHS mode. When I load and save fragmented files in my normal OS I create a bitmap of sectors to be loaded/saved and then generate groups of 6 data bytes of the kind used here to load/save adjacent sectors via the BIOS, thereby making it dead easy to transfer 64KB of data at a time without switching back to protected mode [edit: the point being to make it easier to do the required processing in real mode which I am always keen to keep to a minimum]. It also works in LBA mode, though there are faster ways of doing that as you can load 127 sectors at a time (better to do 64 though) and I use a totally different method to save back to flash drives to reduce wear to the minimum.
Continuation of major WTF (there's no sane excuse)
Who wants to write another sodding real-mode OS! Get into protected mode. I ran my OS for years in protected mode with the interrupts disabled because it was all I needed as a platform for running other stuff on that I was developing (which was always more important than the OS).

This is part of a jump that jumps to a jump that jumps to a jump(!)
Makes it easier to modify stuff in the boot sector if you're a direct machine code programmer. You aren't, so you wouldn't understand that, but BwtSecOS is self evidently going to require direct machine programming to begin with.
should be "jmp near 0x7cfe", or just shift the code at 0x7CFE here to avoid the need for pointless JMPs
My indexing system is designed to work with 32-bit code only so it doesn't automatically adjust the few sections of real-mode code that I use - it would be overkill to write an indexing system for a mode I almost never use, so using one extra (harmless) jump in a bootsector is no great deal. Yes I could save one byte of code, and make my work a lot harder.
;Retarded puke to read or write sectors (using BIOS function 0x02, 0x03, 0x42 or 0x43 depending on what was written to 0x7CC2 by self modifying code, even though BIOS functions 0x02 and 0x03 are extremely different to BIOS functions 0x42 and 0x43 and
;none of the logic is shared). Desperately needs to be replaced by a function pointer (e.g. "call [disk_function]").
You made a fuss about me using one extra byte a moment ago and a billionth of a second of extra boot time, but now you want me to use two extra bytes and waste a billionth of a second here instead! The BIOS functions for CHS and LBA are very different, but fully compatible in terms of what you load the registers with before calling the BIOS. I've saved a lot of space by writing the code the way I have.
WARNING: This code also uses "lodsb" in a pointless and retarded way instead of doing "mov reg,[address]". This complicates everything for no sane reason.
Have you ever compared the number of machine code bytes used by those instructions? My code is designed for compactness rather than pointless bloat.
xchg ax,si ;si = 0x7C29, ax = undefined (should be "mov si,[0x7c0e]" or "mov si,0x7C29")
xchg ax.si uses a single instruction byte. This was done for a very good reason, because when you're learning to program in machine code it takes a while to get up to speed with some of the harder-to-form machine code instructions: anyone trying to use BwtSecOS is likely to prefer doing some indirect loads to begin with, and here I made the machine code more readable for them without losing a byte.
WARNING: There's no CLD or STD anywhere, so undefined behaviour here..
That's a good 'un - I've lost a point. Need to add a byte to fix that, and find something that can be compressed, which shouldn't be hard. [Edit: two - need it again after BIOS call.]
yes, return with a pointless "RETF" that should be a plain "RET"
Again this is to make it easier to call the procedure without having to work out a sodding jump distance - it's worth losing two bytes for that.
ecx = 0 (WARNING: assuming 80386 or later)
Another point to you - I should have warned people.
Is some sort of flag zero?
Fetches head value from data. [Edit: no point lost or gained - that's just answering a question.]
ax = 0 (should be deleted)
It's function is exactly the same as xor ah,ah here - there's no performance cost, and there may even be a gain.
al = something (should be deleted)
The sec_start_no is somewhat vital.
add cx,ax ;cx = something (should be "movzx cx,byte [si+0x3]")
My way improves machine code readability.
mov al,[si+0x2] ;ax = something (should be "movzx ax,byte [si+0x2]")
Ditto.
mov dx,ax ;dx = something (never used, should be deleted)
mov dl,0x24 ;dx = 0x0024 (should be "mov dx,0x0024")
Same end result, but you've saved infinitesimal processor time so take a point for that.
(WARNING: highest 16-bits of multiplication in DX are lost)
There aren't >65536 sectors on a floppy disk. [No loss of point though - could be relevant if you aren't restricting yourself to floppy-disk size.]
mov eax,[0x7c20] ;ax = 0x00000000 (value never modified)
Maybe that's because it's where someone will manually write in the LBA locaction if BwtSecOS is run from a partition, as explained in the instructions.
mov ah,al ;ah = something (should probably be "shl ax,8")
mov al,0x0 ;ax = something << 8 (should probably be "shl ax,8")
Those instructions will cost you an extra byte each time.
xchg ax,bx ;bx = something, ax = undefined (should probably be "mov bx,ax")
Machine code programmers' trick to save a byte.
xchg ax,dx ;dx = something, ax = undefined (should probably be "mov dx,ax")
Ditto.
xchg ax,cx ;ch = cylinder, cl = sector, ax = undefined (should probably be "mov cx,ax" or maybe "mov ch,[cylinder]; mov cl,[sector]")
Ditto.
00007CC1 B402 mov ah,0x2 ;WARNING: Value 0x02 is modified by self modifying code
Harmless and saves two bytes.
If error, jump to error handler that doesn't do anything to handle the error at all
The error handling code there is incomplete: I never got round to finishing because it did the job well enough for my needs - the key thing it does is check to see if any sectors were loaded, and I've just remembered as I write this that it does that because the BIOS was taking two goes to get to track 0 from track 79, so if it tried to read track 0 when it wasn't there, this was the most economical way of making it have another go at moving there.

Okay then. Who wants to add up the score...?

[Edit: no, it won't be that easy - he'll want to argue this till the cows come home.]
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: How to make a real stand-alone system?

Post by Brendan »

Hi,
DavidCooper wrote:
Brendan wrote:Hi,
Brendan wrote:Now all we need is for someone to add comments, so that it's easy to see how bad this code actually is.
It isn't ideal, but it's a hell of a lot better than your ludicrous objections suggest. I will comment on every single negative comment you've made. It'll be fun to add up the score in terms of the good ones versus the bad ones:-
;Get byte from keyboard with race conditions (instead of using the BIOS function that is designed to do this right)
Designed only for use with interrupts disabled.
If BIOS IRQ handler hasn't already got the byte...
Not possible with interrupts disabled.
Interrupts shouldn't be disabled by default; and you should be using Int 0x16 anyway (which would be smaller and less error-prone).
DavidCooper wrote:
Brendan wrote:ready for a broken/idiotic delay...Broken/idiotic delay (may take 0 cycles on some CPUs)...ready for a broken/idiotic delay (contents of CL is undefined)
Delays are not idiotic on the rare type of machine these delays are designed to protect,
Wrong. I was specifically thinking of old Cyrix CPUs when I wrote this (Cyrix CPUs caused Linux developers similar problems with their old/broken tiny delays).
DavidCooper wrote:and CL=0 after the loops run out, so the loop instruction decs it to 15535 before comparing with zero on the kind of machine this is intended to protect.
Wrong. If the branch at 0x7C46 ("jnz 0x7C4E ;jump if new input") is taken, then nothing sets CL to anything before the loop at 0x7C50.
DavidCooper wrote:
00007C54 CB retf ;Pointless "retf" for no reason (should be "ret")
Ignorant fool doesn't recognise that it's easier to call a routine with a far call as you don't have to work out the jump distance. This makes it much easier to develop the OS further.
Ignorant fool would be using broken tools that fail to relieve the programmer from the hassle of calculating jump distances.
DavidCooper wrote:
;Retarded self-modifying code to screw up CPU's trace cache instead of using a simple variable
How much speed do you think matters at this primitive level while calling the BIOS? What I've gained here is more compact code. I'd have thought you'd have understood the need for that here.
It's not more compact, it's just pointlessly obfusticated.
DavidCooper wrote:
Major WTF (there's no sane excuse for IRQs to be disabled by default)
The first thing I did when I wrote my main OS was switch to protected mode, and it was a long time before I bothered with interrupts other than when returning to load/save data. I never bothered to read up on how to get keyboard input from the BIOS as you can't do that from protected mode and I wanted to work in 32-bit mode as much as possible.
*facepalm* (this is just a silly wrapper around a retarded "swiss army knife" mess)
That is a means to load and save data efficiently through the BIOS in CHS mode. When I load and save fragmented files in my normal OS I create a bitmap of sectors to be loaded/saved and then generate groups of 6 data bytes of the kind used here to load/save adjacent sectors via the BIOS, thereby making it dead easy to transfer 64KB of data at a time without switching back to protected mode. It also works in LBA mode, though there are faster ways of doing that as you can load 127 sectors at a time (better to do 64 though) and I use a totally different method to save back to flash drives to reduce wear to the minimum.
Continuation of major WTF (there's no sane excuse)
Who wants to write another sodding real-mode OS! Get into protected mode. I ran my OS for years in protected mode with the interrupts disabled because it was all I needed as a platform for running other stuff on that I was developing (which was always more important than the OS).
I'm only able to comment on the code I can see (which doesn't include your OS, or anything that uses protected mode).
DavidCooper wrote:
This is part of a jump that jumps to a jump that jumps to a jump(!)
Makes it easier to modify stuff in the boot sector if you're a direct machine code programmer. You aren't, so you wouldn't understand that, but BwtSecOS is self evidently going to require direct machine programming to begin with.
Don't be fooled - I used to do similar "direct machine code" stuff (for a 6502) when I was a kid (too young and too stupid to use better tools). Of course I wrote an assembler for 6502 not long after.
DavidCooper wrote:
should be "jmp near 0x7cfe", or just shift the code at 0x7CFE here to avoid the need for pointless JMPs
My indexing system is designed to work with 32-bit code only so it doesn't automatically adjust the few sections of real-mode code that I use - it would be overkill to write an indexing system for a mode I almost never use, so using a one extra (harmless) jump in a bootsector is no great deal. Yes I could save one byte of code, and make my work a lot harder.
Another "my code is bad because my tools are bad" excuse.
DavidCooper wrote:
;Retarded puke to read or write sectors (using BIOS function 0x02, 0x03, 0x42 or 0x43 depending on what was written to 0x7CC2 by self modifying code, even though BIOS functions 0x02 and 0x03 are extremely different to BIOS functions 0x42 and 0x43 and
;none of the logic is shared). Desperately needs to be replaced by a function pointer (e.g. "call [disk_function]").
You made a fuss about me using one extra byte a moment ago and a billionth of a second of extra boot time, but now you want me to use two extra bytes and waste a billionth of a second here instead! The BIOS functions for CHS and LBA are very different, but fully compatible in terms of what you load the registers with before calling the BIOS. I've saved a lot of space by writing the code the way I have.
Bullshit. It's a bloated mess that could/should be much more compact, starting with hard-coding the DAP (instead of generating it from hard-coded values) and having a function that converts LBA (from DAP) to CHS for the "old int 0x13" functions.

Also note that they aren't "BIOS functions for CHS and LBA" - one is for small disks (e.g. floppy) and the other is for large disks. The code I can see has no reason to use "int 0x13 extensions" at all (even on large disks it wouldn't use "cylinder > 1023").
DavidCooper wrote:
WARNING: This code also uses "lodsb" in a pointless and retarded way instead of doing "mov reg,[address]". This complicates everything for no sane reason.
Have you ever compared the number of machine code bytes used by those instructions? My code is designed for compactness rather than pointless bloat.
Bullshit. For an example consider this code:

Code: Select all

000000A7  AC                lodsb                 ;fetch addrMSB from data
000000A8  8AE0              mov ah,al             ;put in AH
000000AA  B000              mov al,0x0            ;complete the addr
000000AC  A3147C            mov [0x7c14],ax       ;post into DAP
000000AF  93                xchg ax,bx            ;and put in BX for CHS
000000B0  AC                lodsb                 ;fetch head no from data
000000B1  8AE0              mov ah,al             ;put in AH
000000B3  A0287C            mov al,[0x7c28]       ;put drive-number in AL
000000B6  92                xchg ax,dx            ;move into DX
000000B7  AC                lodsb                 ;fetch track no
000000B8  50                push ax               ;put on stack for display later
000000B9  8AE0              mov ah,al             ;move to AH
000000BB  AC                lodsb                 ;fetch start_sec no
000000BC  91                xchg ax,cx            ;put these in CX
000000BD  AC                lodsb                 ;fetch no_of_secs which stays in AL
000000BE  A2127C            mov [0x7c12],al       ;post into DAP
000000C1
And this alternative:

Code: Select all

000000A7  0FB65C01          movzx bx,[si+0x1]    ;fetch addrMSB from data
000000AB  891E147C          mov [0x7c14],bx      ;post into DAP
000000AF  8A7402            mov dh,[si+0x2]      ;fetch head no from data
000000B2  8A16287C          mov dl,[0x7c28]      ;put drive-number in DL
000000B6  8A6C03            mov ch,[si+0x3]      ;fetch track no
000000B9  8A4C04            mov cl,[si+0x4]      ;fetch start_sec no
000000BC  8A4405            mov al,[si+0x5]      ;fetch no_of_secs which stays in AL
000000BF  A2127C            mov [0x7c12],al      ;post into DAP
000000C2
My version is 1 byte longer and doesn't do the " push ax ;put on stack for display later"; but it makes it obvious that the layout of the data needs to be improved. With the layout of the data optimised you get this:

Code: Select all

000000A7  8B5C02            mov bx,[si+0x2]       ;fetch addrMSB from data
000000AA  891E147C          mov [0x7c14],bx       ;post into DAP
000000AE  8B5404            mov dx,[si+0x4]       ;fetch head no and drive-number
000000B1  8B4C06            mov cx,[si+0x6]       ;fetch track no and start_sec no
000000B4  8A4408            mov al,[si+0x8]       ;fetch no_of_secs which stays in AL
000000B7  A2127C            mov [0x7c12],al       ;post into DAP
000000BA
Notice that this is 7 bytes less than yours; but doesn't do the "push ax" - instead the "pop ax" would be replaced with a "mov". This would add another few bytes to code elsewhere, making my version 5 bytes less than your slower and harder to read/maintain version.
DavidCooper wrote:
xchg ax,si ;si = 0x7C29, ax = undefined (should be "mov si,[0x7c0e]" or "mov si,0x7C29")
xchg ax.si uses a single instruction byte. This was done for a very good reason, because when you're learning to program in machine code it takes a while to get up to speed with some of the harder-to-form machine code instructions: anyone trying to use BwtSecOS is likely to prefer doing some indirect loads to begin with, and here I made the machine code more readable for them without losing a byte.
Another "my code is bad because my tools are bad" excuse.
DavidCooper wrote:
yes, return with a pointless "RETF" that should be a plain "RET"
Again this is to make it easier to call the procedure without having to work out a sodding jump distance - it's worth losing two bytes for that.
Another "my code is bad because my tools are bad" excuse.
DavidCooper wrote:
ecx = 0 (WARNING: assuming 80386 or later)
Another point to you - I should have warned people.
Um, no - you should've tested if the CPU is 80386 or later and warned the user (or avoided using 32-bit registers, which would've been easier given that you ignore the highest 16-bits of the multiplication anyway).
DavidCooper wrote:
Is some sort of flag zero?
Fetches head value from data
I was too lazy to figure it out - most sane programmers use variable names and comments for this reason (e.g. "mov al,[si+myStructure.head] ;al = get head").
DavidCooper wrote:
ax = 0 (should be deleted)
It's function is exactly the same as xor ah,ah here - there's no performance cost, and there may even be a gain.
Compare this:

Code: Select all

00007C87  33C0              xor ax,ax                ;ax = 0 (should be deleted)
00007C89  8A4403            mov al,[si+0x3]          ;al = something (should be deleted)
00007C8C  03C8              add cx,ax                ;cx = something (should be "movzx cx,byte [si+0x3]")
To this:

Code: Select all

000000A7  0FB64C03          movzx cx,[si+0x3]
Your version is 7 bytes and 3 instructions, while mine is only 4 bytes and 1 instruction and is faster and easier to read/maintain.
DavidCooper wrote:
mov dx,ax ;dx = something (never used, should be deleted)
mov dl,0x24 ;dx = 0x0024 (should be "mov dx,0x0024")
Same end result, but you've saved processor time.
Wrong. You've increased processor time because "mov dl,0x24" creates a false dependency on the old value in DX (which has a false dependency on the value of AX, which depends on a load from memory). Basically you've got a large dependency chain that prevents the CPU's "out-of-order execution" and kills performance.
DavidCooper wrote:
(WARNING: highest 16-bits of multiplication in DX are lost)
There aren't >65536 sectors on a floppy disk.
So why did you bother with "int 0x13 extensions"?
DavidCooper wrote:
mov eax,[0x7c20] ;ax = 0x00000000 (value never modified)
Maybe that's because it's where someone will manually write in the LBA locaction if BwtSecOS is run from a partition, as explained in the instructions.
Ah - OK. I'm used to sane tools where you could just "#define PARTITION_START 0x000000" and "mov eax,PARTITION_START".
DavidCooper wrote:
mov ah,al ;ah = something (should probably be "shl ax,8")
mov al,0x0 ;ax = something << 8 (should probably be "shl ax,8")
Those instructions will cost you an extra byte each time.

Code: Select all

00000000  88C4              mov ah,al
00000002  B000              mov al,0x0
00000004  C1E008            shl ax,0x8
4 bytes vs. 3 bytes.
DavidCooper wrote:
xchg ax,bx ;bx = something, ax = undefined (should probably be "mov bx,ax")
Machine code programmers' trick to save a byte.
Machine code programmer's trick to hamper the CPU's "register renaming" and make code slow.
DavidCooper wrote:Okay then. Who wants to add up the score...
My conclusion is that you've deluded yourself into believing that your "tools" and abilities are superior, when in practice the "direct machine programming" approach is so fundamentally flawed that it's impossible for anyone to create adequate code (for any definition of "adequate" - size, speed, maintainability, etc) using this approach.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
dozniak
Member
Member
Posts: 723
Joined: Thu Jul 12, 2012 7:29 am
Location: Tallinn, Estonia

Re: How to make a real stand-alone system?

Post by dozniak »

Brendan wrote:Ah - OK. I'm used to sane tools
Simply remember the purpose of this exercise. Read the topic name if you missed it.
This is completely standalone, however broken or inconvenient; you're supposed to boot it and enter your own much better version by hand.
Learn to read.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: How to make a real stand-alone system?

Post by Brendan »

Hi,
dozniak wrote:
Brendan wrote:Ah - OK. I'm used to sane tools
Simply remember the purpose of this exercise. Read the topic name if you missed it.
Um, the topic name isn't very descriptive (e.g. I'd include Ubuntu as a "real stand-alone system").
dozniak wrote:This is completely standalone, however broken or inconvenient; you're supposed to boot it and enter your own much better version by hand.
Nothing would prevent you from using normal tools, printing out a hex dump, then entering that hexdump by hand.

Also, the "rules" set out by Antii in the first post include this:
Antti wrote:Only a boot sector is written beforehand.
Basically, the boot sector itself didn't need to be written in machine code at all.

Finally, Antii (and probably everyone else, except DavidCooper) understand the limitations. E.g.:
Antti wrote:Of course there is no sense doing this but it would be a nice theoretical project.
Basically, it's just a little challenge for fun. DavidCooper never really understood these limitations and is still seriously attempting to use machine code. He's not doing it as a fun little challenge. This is sad, as he seems intelligent enough to achieve something better than a joke project.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Mikemk
Member
Member
Posts: 409
Joined: Sat Oct 22, 2011 12:27 pm

Re: How to make a real stand-alone system?

Post by Mikemk »

Brendan wrote:
dozniak wrote:This is completely standalone, however broken or inconvenient; you're supposed to boot it and enter your own much better version by hand.
Nothing would prevent you from using normal tools, printing out a hex dump, then entering that hexdump by hand.
Agreed
Also, the "rules" set out by Antii in the first post include this:
Antti wrote:Only a boot sector is written beforehand.
Basically, the boot sector itself didn't need to be written in machine code at all.

Finally, Antii (and probably everyone else, except DavidCooper) understand the limitations. E.g.:
Antti wrote:Of course there is no sense doing this but it would be a nice theoretical project.
Basically, it's just a little challenge for fun. DavidCooper never really understood these limitations and is still seriously attempting to use machine code. He's not doing it as a fun little challenge. This is sad, as he seems intelligent enough to achieve something better than a joke project.
Actually, a program of this nature would be incredibly useful for law enforcement and forensics. Not to mention the usefulness in our field if it was used AS your debugger.

In addition, a college professor could, say, give it to his/her students (maybe? what's the license?) as a teaching excercize (how do you spell that?).
The lesson plan would be, "Why not to do stupid things" or "history of antique and entirely obsolete computers."
Programming is 80% Math, 20% Grammar, and 10% Creativity <--- Do not make fun of my joke!
If you're new, check this out.
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: How to make a real stand-alone system?

Post by Antti »

Well, this is not as fun as I thought. I did not define "rules" because this is not a competition. I just liked the idea that it would be possible to make a stand-alone system immediately. If we had just a PC, media that contains this magic boot sector, "sufficient amount of manuals", and plenty of time, it would be possible to build an infinitely complex system.
Antti wrote:First thing to do is to get rid of the machine code programming.
Machine code cannot be better than assembly. Assembly can be better than, for example, C.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: How to make a real stand-alone system?

Post by Combuster »

Machine code cannot be better than assembly.
Try copying assembly or machine code into some computer's RAM and you'll know better :mrgreen:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Mikemk
Member
Member
Posts: 409
Joined: Sat Oct 22, 2011 12:27 pm

Re: How to make a real stand-alone system?

Post by Mikemk »

Combuster wrote:
Machine code cannot be better than assembly.
Try copying assembly or machine code into some computer's RAM and you'll know better :mrgreen:
Technically, machine code and assembly are different syntaxes of the same thing.
Programming is 80% Math, 20% Grammar, and 10% Creativity <--- Do not make fun of my joke!
If you're new, check this out.
User avatar
iansjack
Member
Member
Posts: 4685
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: How to make a real stand-alone system?

Post by iansjack »

Technically, machine code and assembly are different syntaxes of the same thing.
Well, technically, C and machine code are different syntaxes of the same thing. Nevertheless, there are valid reasons to distinguish between the two.
User avatar
Griwes
Member
Member
Posts: 374
Joined: Sat Jul 30, 2011 10:07 am
Libera.chat IRC: Griwes
Location: Wrocław/Racibórz, Poland
Contact:

Re: How to make a real stand-alone system?

Post by Griwes »

iansjack wrote:
Technically, machine code and assembly are different syntaxes of the same thing.
Well, technically, C and machine code are different syntaxes of the same thing. Nevertheless, there are valid reasons to distinguish between the two.
No, they are not, C doesn't translate 1:1 to machine code. Assembly does. You can have different ways of compiling "if (a) b(); else c();" in C (at least two), but you have only one way of assembling given assembly code.
Reaver Project :: Repository :: Ohloh project page
<klange> This is a horror story about what happens when you need a hammer and all you have is the skulls of the damned.
<drake1> as long as the lock is read and modified by atomic operations
Locked