├── .gitignore ├── 文档模板 └── 测试用例模板.xlsx ├── 第07话 └── start.asm ├── 第11话 └── mov.asm ├── 第12话 └── debug.asm ├── 第14话 ├── adcsbb.asm ├── addsub.asm └── gauss.asm ├── 第15话 ├── divbig.asm ├── muldiv.asm └── stack.asm ├── 第16话 └── printstring.asm ├── 第17话 ├── data.asm └── readhdd.asm ├── 第18话 ├── BootLoader.asm └── Program.asm ├── 第19话 ├── BootLoader.asm └── Program.asm ├── 第20话 └── Program.asm ├── 第22话 └── 32bits.asm ├── 第23话 ├── BootLoader.asm └── Initial.asm ├── 第27话 └── SimpleInitialL.asm ├── 第43话 └── sms.c ├── 第44话 └── sms.c ├── 第45话 └── list.c └── 第46话 ├── blue.c └── list.c /.gitignore: -------------------------------------------------------------------------------- 1 | TEST/ 2 | *bin 3 | *lst -------------------------------------------------------------------------------- /文档模板/测试用例模板.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanyugang/CodingMaster/63e630f228c66d2245aaf082877ad99ba4f4c562/文档模板/测试用例模板.xlsx -------------------------------------------------------------------------------- /第07话/start.asm: -------------------------------------------------------------------------------- 1 | ;*********************************************** 2 | ;代码作者:谭玉刚 3 | ;教程链接: 4 | ;https://www.bilibili.com/video/BV1s5411n7Tr/ 5 | ;https://www.youtube.com/watch?v=YGdjmX-ZgDQ 6 | ;不要错过: 7 | ;B站/微信/油管/头条/知乎/大鱼/企鹅:谭玉刚 8 | ;百度/微博:玉刚谈 9 | ;来聊天呀:636093821(QQ群) 10 | ;*********************************************** 11 | mov ax, 0b800h 12 | mov ds, ax 13 | 14 | mov byte [0x00],'2' 15 | mov byte [0x02],'0' 16 | mov byte [0x04],'2' 17 | mov byte [0x06],'1' 18 | mov byte [0x08],',' 19 | mov byte [0x0a],'H' 20 | mov byte [0x0c],'a' 21 | mov byte [0x0e],'p' 22 | mov byte [0x10],'p' 23 | mov byte [0x12],'y' 24 | mov byte [0x14],' ' 25 | mov byte [0x16],'N' 26 | mov byte [0x18],'i' 27 | mov byte [0x1a],'u' 28 | mov byte [0x1c],' ' 29 | mov byte [0x1e],'Y' 30 | mov byte [0x20],'e' 31 | mov byte [0x22],'a' 32 | mov byte [0x24],'r' 33 | mov byte [0x26],'!' 34 | 35 | jmp $ 36 | 37 | times 510-($-$$) db 0 38 | db 0x55,0xaa 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /第11话/mov.asm: -------------------------------------------------------------------------------- 1 | ;*********************************************** 2 | ;代码作者:谭玉刚 3 | ;教程链接: 4 | ;https://www.bilibili.com/video/BV1AT4y1N71D/ 5 | ;https://www.youtube.com/watch?v=Ar-q-k6KZJg 6 | ;不要错过: 7 | ;B站/微信/油管/头条/知乎/大鱼/企鹅:谭玉刚 8 | ;百度/微博:玉刚谈 9 | ;来聊天呀:1054728152(QQ群) 10 | ;*********************************************** 11 | mov 0xb700, 0xb800 12 | mov [0x01], 0xb800 13 | mov byte [0x01], 0xb800 14 | mov word [0x01], 0xb800 15 | mov [0x01], [0x02] 16 | mov ax, [0x02] 17 | mov [0x03], ax 18 | mov ds, [0x05] 19 | mov [0x04], ds 20 | mov ax, bx 21 | mov cx, dl 22 | mov cs, ds -------------------------------------------------------------------------------- /第12话/debug.asm: -------------------------------------------------------------------------------- 1 | ;*********************************************** 2 | ;代码作者:谭玉刚 3 | ;教程链接: 4 | ;https://www.bilibili.com/video/BV1Kz4y1U7Mj/ 5 | ;https://www.youtube.com/watch?v=EJgdGTAixVg&t=5s 6 | ;不要错过: 7 | ;B站/微信/油管/头条/知乎/大鱼/企鹅:谭玉刚 8 | ;百度/微博:玉刚谈 9 | ;来聊天呀:1054728152(QQ群) 10 | ;*********************************************** 11 | mov ax, 0x7c00 12 | mov ds, ax 13 | mov bx, 0x353637 14 | mov byte [0xf1], 'H' 15 | mov byte [0xf2], 0x3839 16 | jmp $ 17 | times 510-($-$$) db 0 18 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第14话/adcsbb.asm: -------------------------------------------------------------------------------- 1 | ;*********************************************** 2 | ;代码作者:谭玉刚 3 | ;教程链接: 4 | ;https://www.bilibili.com/video/BV1py4y1a7C1/ 5 | ;https://www.youtube.com/watch?v=UjKnA1EhVco 6 | ;不要错过: 7 | ;B站/微信/油管/头条/知乎/大鱼/企鹅:谭玉刚 8 | ;百度/微博:玉刚谈 9 | ;来聊天呀:1054728152(QQ群) 10 | ;*********************************************** 11 | ;bx:ax=0x0001f000 12 | mov bx, 0x0001 13 | mov ax, 0xf000 14 | ;dx:cx=0x00101000 15 | mov dx, 0x0010 16 | mov cx, 0x1000 17 | ;低位相加 18 | add ax, cx 19 | ;高位相加 20 | adc bx, dx 21 | ;和应该在bx:ax=0x00120000 22 | jmp $ 23 | times 510-($-$$) db 0 24 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第14话/addsub.asm: -------------------------------------------------------------------------------- 1 | ;不产生进位的加法 2 | mov ax, 0x0001 3 | mov bx, 0x0002 4 | add ax, bx 5 | ;产生进位的加法 6 | mov ax, 0xf000 7 | mov bx, 0x1000 8 | add ax, bx 9 | ;不产生借位的减法 10 | mov cx, 0x0003 11 | mov dx, 0x0002 12 | sub cx, dx 13 | ;产生借位的减法 14 | mov cx, 0x0001 15 | mov dx, 0x0002 16 | sub cx, dx 17 | 18 | xuanmai: jmp xuanmai 19 | times 510-($-$$) db 0 20 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第14话/gauss.asm: -------------------------------------------------------------------------------- 1 | ;设定循环次数 2 | mov cx, 100 3 | ;初始化ax 4 | mov ax, 0x0000 5 | ;循环部分 6 | sum: 7 | add ax, cx 8 | loop sum 9 | 10 | jmp $ 11 | times 510-($-$$) db 0 12 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第15话/divbig.asm: -------------------------------------------------------------------------------- 1 | ;*********************************************** 2 | ;代码作者:谭玉刚 3 | ;教程链接: 4 | ;https://www.bilibili.com/video/BV1dh411D7nV/ 5 | ;https://www.youtube.com/watch?v=lq6DSk3QoAU 6 | ;不要错过: 7 | ;B站/微信/油管/头条/知乎/大鱼/企鹅:谭玉刚 8 | ;百度/微博:玉刚谈 9 | ;来聊天呀:1054728152(QQ群) 10 | ;*********************************************** 11 | ;被除数0x00090006 12 | mov dx, 0x0009 13 | mov ax, 0x0006 14 | ;除数0x0002 15 | mov cx, 0x0002 16 | push ax 17 | mov ax, dx 18 | mov dx, 0 19 | ;第一次除法,高位 20 | div cx 21 | mov bx, ax 22 | ;第二次除法,低位 23 | pop ax 24 | div cx 25 | 26 | jmp $ 27 | times 510-($-$$) db 0 28 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第15话/muldiv.asm: -------------------------------------------------------------------------------- 1 | ;8位乘法 2 | mov al, 0xf0 3 | mov ah, 0x02 4 | mul ah 5 | ;16位乘法 6 | mov ax, 0xf000 7 | mov bx, 0x0002 8 | mul bx 9 | ;16位除法 10 | mov ax, 0x0004 11 | mov bl, 0x02 12 | div bl 13 | ;32位除法 14 | mov dx, 0x0008 15 | mov ax, 0x0006 16 | mov cx, 0x0002 17 | div cx 18 | ;循环及补0 19 | jmp $ 20 | times 510-($-$$) db 0 21 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第15话/stack.asm: -------------------------------------------------------------------------------- 1 | ;设置ss寄存器 2 | mov bx, 0x0000 3 | mov ss, bx 4 | ;设置sp寄存器 5 | mov sp, 0x0000 6 | ;ax压入栈 7 | push ax 8 | ;ax弹出栈 9 | pop ax 10 | ;循环及补0 11 | jmp $ 12 | times 510-($-$$) db 0 13 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第16话/printstring.asm: -------------------------------------------------------------------------------- 1 | ;*********************************************** 2 | ;代码作者:谭玉刚 3 | ;教程链接: 4 | ;https://www.bilibili.com/video/BV1Lp4y1h7vg/ 5 | ;https://www.youtube.com/watch?v=wbeLHALXRPw 6 | ;不要错过: 7 | ;B站/微信/油管/头条/知乎/大鱼/企鹅:谭玉刚 8 | ;百度/微博:玉刚谈 9 | ;来聊天呀:1054728152(QQ群) 10 | ;*********************************************** 11 | NUL equ 0x00 12 | SETCHAR equ 0x07 13 | VIDEOMEM equ 0xb800 14 | STRINGLEN equ 0xffff 15 | section code align=16 vstart=0x7c00 16 | mov si, SayHello 17 | xor di, di 18 | call PrintString 19 | mov si, SayByeBye 20 | call PrintString 21 | jmp End 22 | PrintString: 23 | .setup: 24 | mov ax, VIDEOMEM 25 | mov es, ax 26 | 27 | mov bh, SETCHAR 28 | mov cx, STRINGLEN 29 | 30 | .printchar: 31 | mov bl, [ds:si] 32 | inc si 33 | mov [es:di], bl 34 | inc di 35 | mov [es:di], bh 36 | inc di 37 | or bl, NUL 38 | jz .return 39 | loop .printchar 40 | .return: 41 | ret 42 | 43 | SayHello db 'Hi there,I am Coding Master!' 44 | db 0x00 45 | SayByeBye db 'I think you can handle it,bye!' 46 | db 0x00 47 | 48 | End: jmp End 49 | times 510-($-$$) db 0 50 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第17话/data.asm: -------------------------------------------------------------------------------- 1 | ;*********************************************** 2 | ;代码作者:谭玉刚 3 | ;教程链接: 4 | ;https://www.bilibili.com/video/BV1sK4y1D7oP/ 5 | ;https://www.youtube.com/watch?v=UNwVSXUCDW0 6 | ;不要错过: 7 | ;B站/微信/油管/头条/知乎/大鱼/企鹅:谭玉刚 8 | ;百度/微博:玉刚谈 9 | ;来聊天呀:1054728152(QQ群) 10 | ;*********************************************** 11 | Data db 'Hi, I come from hard disk drive!' 12 | db 0x00 -------------------------------------------------------------------------------- /第17话/readhdd.asm: -------------------------------------------------------------------------------- 1 | HDDPORT equ 0x1f0 2 | NUL equ 0x00 3 | SETCHAR equ 0x07 4 | VIDEOMEM equ 0xb800 5 | STRINGLEN equ 0xffff 6 | section code align=16 vstart=0x7c00 7 | 8 | mov si, [READSTART] 9 | mov cx, [READSTART+0x02] 10 | mov al, [SECTORNUM] 11 | push ax 12 | 13 | mov ax, [DESTMEN] 14 | mov dx, [DESTMEN+0x02] 15 | mov bx, 16 16 | div bx 17 | 18 | mov ds, ax 19 | xor di, di 20 | pop ax 21 | 22 | call ReadHDD 23 | xor si, si 24 | call PrintString 25 | jmp End 26 | 27 | ReadHDD: 28 | push ax 29 | push bx 30 | push cx 31 | push dx 32 | 33 | mov dx, HDDPORT+2 34 | out dx, al 35 | 36 | mov dx, HDDPORT+3 37 | mov ax, si 38 | out dx, al 39 | 40 | mov dx, HDDPORT+4 41 | mov al, ah 42 | out dx, al 43 | 44 | mov dx, HDDPORT+5 45 | mov ax, cx 46 | out dx, al 47 | 48 | mov dx, HDDPORT+6 49 | mov al, ah 50 | mov ah, 0xe0 51 | or al, ah 52 | out dx, al 53 | 54 | mov dx, HDDPORT+7 55 | mov al, 0x20 56 | out dx, al 57 | 58 | .waits: 59 | in al, dx 60 | and al, 0x88 61 | cmp al, 0x08 62 | jnz .waits 63 | 64 | mov dx, HDDPORT 65 | mov cx, 256 66 | 67 | .readword: 68 | in ax, dx 69 | mov [ds:di], ax 70 | add di, 2 71 | or ah, 0x00 72 | jnz .readword 73 | 74 | .return: 75 | pop dx 76 | pop cx 77 | pop bx 78 | pop ax 79 | 80 | ret 81 | 82 | PrintString: 83 | .setup: 84 | push ax 85 | push bx 86 | push cx 87 | push dx 88 | mov ax, VIDEOMEM 89 | mov es, ax 90 | xor di, di 91 | 92 | mov bh, SETCHAR 93 | mov cx, STRINGLEN 94 | 95 | .printchar: 96 | mov bl, [ds:si] 97 | inc si 98 | mov [es:di], bl 99 | inc di 100 | mov [es:di], bh 101 | inc di 102 | or bl, NUL 103 | jz .return 104 | loop .printchar 105 | .return: 106 | mov bx, di 107 | pop dx 108 | pop cx 109 | pop bx 110 | pop ax 111 | ret 112 | 113 | READSTART dd 10 114 | SECTORNUM db 1 115 | DESTMEN dd 0x10000 116 | 117 | End: jmp End 118 | times 510-($-$$) db 0 119 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第18话/BootLoader.asm: -------------------------------------------------------------------------------- 1 | ;*********************************************** 2 | ;代码作者:谭玉刚 3 | ;教程链接: 4 | ;https://www.bilibili.com/video/BV1Wb4y1Q7sb/ 5 | ;https://www.youtube.com/watch?v=XNoBS15To9E 6 | ;不要错过: 7 | ;B站/微信/油管/头条/知乎/大鱼/企鹅:谭玉刚 8 | ;百度/微博:玉刚谈 9 | ;来聊天呀:1054728152(QQ群) 10 | ;*********************************************** 11 | HDDPORT equ 0x1f0 12 | section code align=16 vstart=0x7c00 13 | mov si, [READSTART] 14 | mov cx, [READSTART+2] 15 | mov al, [SECTORNUM] 16 | push ax 17 | ;Setup the destnation 18 | mov ax, [DESTMEN] 19 | mov dx, [DESTMEN+0x02] 20 | mov bx, 16 21 | div bx 22 | 23 | mov ds, ax 24 | xor di, di 25 | pop ax 26 | ;read the first sector 27 | call ReadHDD 28 | 29 | ResetSegment: 30 | mov bx, 0x04 31 | mov cl, [0x10] 32 | 33 | .reset: 34 | mov ax, [bx] 35 | mov dx, [bx+2] 36 | add ax, [cs:DESTMEN] 37 | adc dx, [cs:DESTMEN+2] 38 | 39 | 40 | mov si, 16 41 | div si 42 | mov [bx], ax 43 | add bx, 4 44 | loop .reset 45 | 46 | ResetEntry: 47 | mov ax, [0x13] 48 | mov dx, [0x15] 49 | add ax, [cs:DESTMEN] 50 | adc dx, [cs:DESTMEN+2] 51 | 52 | mov si, 16 53 | div si 54 | 55 | mov [0x13], ax 56 | 57 | jmp far [0x11] 58 | ReadHDD: 59 | push ax 60 | push bx 61 | push cx 62 | push dx 63 | 64 | mov dx, HDDPORT+2 65 | out dx, al 66 | 67 | mov dx, HDDPORT+3 68 | mov ax, si 69 | out dx, al 70 | 71 | mov dx, HDDPORT+4 72 | mov al, ah 73 | out dx, al 74 | 75 | mov dx, HDDPORT+5 76 | mov ax, cx 77 | out dx, al 78 | 79 | mov dx, HDDPORT+6 80 | mov al, ah 81 | mov ah, 0xe0 82 | or al, ah 83 | out dx, al 84 | 85 | mov dx, HDDPORT+7 86 | mov al, 0x20 87 | out dx, al 88 | 89 | .waits: 90 | in al, dx 91 | and al, 0x88 92 | cmp al, 0x08 93 | jnz .waits 94 | 95 | mov dx, HDDPORT 96 | mov cx, 256 97 | 98 | .readword: 99 | in ax, dx 100 | mov [ds:di], ax 101 | add di, 2 102 | ;or ah, 0x00 103 | ;jnz .readword 104 | loop .readword 105 | .return: 106 | pop dx 107 | pop cx 108 | pop bx 109 | pop ax 110 | 111 | ret 112 | 113 | READSTART dd 1 114 | SECTORNUM db 1 115 | DESTMEN dd 0x10000 116 | 117 | End: jmp End 118 | times 510-($-$$) db 0 119 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第18话/Program.asm: -------------------------------------------------------------------------------- 1 | NUL equ 0x00 2 | SETCHAR equ 0x07 3 | VIDEOMEM equ 0xb800 4 | STRINGLEN equ 0xffff 5 | section head align=16 vstart=0 6 | Size dd ProgramEnd;4B 0x00 7 | SegmentAddr: 8 | CodeSeg dd section.code.start;4B 0x04 9 | DataSeg dd section.data.start;4B 0x08 10 | StackSeg dd section.stack.start;4B 0x0c 11 | SegmentNum: 12 | SegNum db (SegmentNum-SegmentAddr)/4;1B 0x10 13 | Entry dw CodeStart;2B 0x11 14 | dd section.code.start;4B 0x13 15 | 16 | section code align=16 vstart=0 17 | CodeStart: 18 | mov ax, [DataSeg] 19 | mov ds, ax 20 | xor si, si 21 | call PrintString 22 | jmp $ 23 | PrintString: 24 | .setup: 25 | push ax 26 | push bx 27 | push cx 28 | push dx 29 | mov ax, VIDEOMEM 30 | mov es, ax 31 | xor di, di 32 | 33 | mov bh, SETCHAR 34 | mov cx, STRINGLEN 35 | 36 | .printchar: 37 | mov bl, [ds:si] 38 | inc si 39 | mov [es:di], bl 40 | inc di 41 | mov [es:di], bh 42 | inc di 43 | or bl, NUL 44 | jz .return 45 | loop .printchar 46 | .return: 47 | mov bx, di 48 | pop dx 49 | pop cx 50 | pop bx 51 | pop ax 52 | ret 53 | section data align=16 vstart=0 54 | Hello db 'Hello,I come from program on sector 1,loaded by bootloader!' 55 | section stack align=16 vstart=0 56 | resb 128 57 | section end align=16 58 | ProgramEnd: -------------------------------------------------------------------------------- /第19话/BootLoader.asm: -------------------------------------------------------------------------------- 1 | ;*********************************************** 2 | ;代码作者:谭玉刚 3 | ;教程链接: 4 | ;https://www.bilibili.com/video/BV1Wb4y1Q7sb/ 5 | ;https://www.youtube.com/watch?v=XNoBS15To9E 6 | ;不要错过: 7 | ;B站/微信/油管/头条/知乎/大鱼/企鹅:谭玉刚 8 | ;百度/微博:玉刚谈 9 | ;来聊天呀:1054728152(QQ群) 10 | ;*********************************************** 11 | HDDPORT equ 0x1f0 12 | section code align=16 vstart=0x7c00 13 | mov si, [READSTART] 14 | mov cx, [READSTART+2] 15 | mov al, [SECTORNUM] 16 | push ax 17 | ;Setup the destnation 18 | mov ax, [DESTMEN] 19 | mov dx, [DESTMEN+0x02] 20 | mov bx, 16 21 | div bx 22 | 23 | mov ds, ax 24 | xor di, di 25 | pop ax 26 | ;read the first sector 27 | call ReadHDD 28 | 29 | ResetSegment: 30 | mov bx, 0x04 31 | mov cl, [0x10] 32 | 33 | .reset: 34 | mov ax, [bx] 35 | mov dx, [bx+2] 36 | add ax, [cs:DESTMEN] 37 | adc dx, [cs:DESTMEN+2] 38 | 39 | mov si, 16 40 | div si 41 | mov [bx], ax 42 | add bx, 4 43 | loop .reset 44 | 45 | ResetEntry: 46 | mov ax, [0x13] 47 | mov dx, [0x15] 48 | add ax, [cs:DESTMEN] 49 | adc dx, [cs:DESTMEN+2] 50 | 51 | mov si, 16 52 | div si 53 | 54 | mov [0x13], ax 55 | 56 | jmp far [0x11] 57 | ReadHDD: 58 | push ax 59 | push bx 60 | push cx 61 | push dx 62 | 63 | mov dx, HDDPORT+2 64 | out dx, al 65 | 66 | mov dx, HDDPORT+3 67 | mov ax, si 68 | out dx, al 69 | 70 | mov dx, HDDPORT+4 71 | mov al, ah 72 | out dx, al 73 | 74 | mov dx, HDDPORT+5 75 | mov ax, cx 76 | out dx, al 77 | 78 | mov dx, HDDPORT+6 79 | mov al, ah 80 | mov ah, 0xe0 81 | or al, ah 82 | out dx, al 83 | 84 | mov dx, HDDPORT+7 85 | mov al, 0x20 86 | out dx, al 87 | 88 | .waits: 89 | in al, dx 90 | and al, 0x88 91 | cmp al, 0x08 92 | jnz .waits 93 | 94 | mov dx, HDDPORT 95 | mov cx, 256 96 | 97 | .readword: 98 | in ax, dx 99 | mov [ds:di], ax 100 | add di, 2 101 | ;or ah, 0x00 102 | ;jnz .readword 103 | loop .readword 104 | .return: 105 | pop dx 106 | pop cx 107 | pop bx 108 | pop ax 109 | 110 | ret 111 | 112 | READSTART dd 1 113 | SECTORNUM db 1 114 | DESTMEN dd 0x10000 115 | 116 | End: jmp End 117 | times 510-($-$$) db 0 118 | db 0x55, 0xaa -------------------------------------------------------------------------------- /第19话/Program.asm: -------------------------------------------------------------------------------- 1 | NUL equ 0x00 2 | SETCHAR equ 0x07 3 | VIDEOMEM equ 0xb800 4 | STRINGLEN equ 0xffff 5 | section head align=16 vstart=0 6 | Size dd ProgramEnd;4B 0x00 7 | SegmentAddr: 8 | CodeSeg dd section.code.start;4B 0x04 9 | DataSeg dd section.data.start;4B 0x08 10 | StackSeg dd section.stack.start;4B 0x0c 11 | SegmentNum: 12 | SegNum db (SegmentNum-SegmentAddr)/4;1B 0x10 13 | Entry dw CodeStart;2B 0x11 14 | dd section.code.start;4B 0x13 15 | 16 | section code align=16 vstart=0 17 | CodeStart: 18 | mov ax, [DataSeg] 19 | mov ds, ax 20 | mov ax, [StackSeg] 21 | mov ss, ax 22 | mov sp, StackEnd 23 | xor si, si 24 | ;mov cx, HelloEnd-Hello 25 | call ClearScreen 26 | call PrintString 27 | jmp $ 28 | ClearScreen: 29 | mov ax, VIDEOMEM 30 | mov es, ax 31 | xor di, di 32 | mov bl, ' ' 33 | mov bh, SETCHAR 34 | mov cx, 2000 35 | .putspace: 36 | mov [es:di], bl 37 | inc di 38 | mov [es:di], bh 39 | inc di 40 | loop .putspace 41 | ret 42 | ;mov cx, STRINGLEN 43 | PrintString: 44 | .setup: 45 | push ax 46 | push bx 47 | push cx 48 | push dx 49 | mov ax, VIDEOMEM 50 | mov es, ax 51 | xor di, di 52 | 53 | mov bh, SETCHAR 54 | mov cx, STRINGLEN 55 | 56 | .printchar: 57 | mov bl, [ds:si] 58 | ;判断并输出回车 59 | cmp bl, 0x0d 60 | jz .putCR 61 | ;判断并输出换行 62 | cmp bl, 0x0a 63 | jz .putLF 64 | ;实际输出字符 65 | or bl, NUL 66 | jz .return 67 | inc si 68 | mov [es:di], bl 69 | inc di 70 | mov [es:di], bh 71 | inc di;2 72 | call SetCursor 73 | jmp .loopEnd 74 | 75 | .putCR:;输出回车 76 | mov bl, 160;80 77 | mov ax, di;10 78 | div bl 79 | shr ax, 8;10 80 | sub di, ax 81 | call SetCursor 82 | inc si 83 | jmp .loopEnd 84 | .putLF:;输出换行 85 | add di, 160;80 86 | call SetCursor 87 | inc si 88 | jmp .loopEnd 89 | 90 | .loopEnd: 91 | loop .printchar 92 | 93 | .return: 94 | mov bx, di 95 | pop dx 96 | pop cx 97 | pop bx 98 | pop ax 99 | ret 100 | SetCursor: 101 | push dx 102 | push bx 103 | push ax 104 | 105 | mov ax, di;2 106 | mov dx, 0 107 | mov bx, 2 108 | div bx 109 | 110 | mov bx, ax 111 | mov dx, 0x3d4 112 | mov al, 0x0e 113 | out dx, al 114 | mov dx, 0x3d5 115 | mov al, bh 116 | out dx, al 117 | mov dx, 0x3d4 118 | mov al, 0x0f 119 | out dx, al 120 | mov al, bl 121 | mov dx, 0x3d5 122 | out dx, al 123 | pop ax 124 | pop bx 125 | pop dx 126 | ret 127 | 128 | section data align=16 vstart=0 129 | Hello db 'Hello,I come from program on sector 1,loaded by bootloader!' 130 | db 0x0d, 0x0a 131 | db 'Haha,This is a new line!' 132 | db 0x0a 133 | db 'Just 0a' 134 | db 0x0d 135 | db 'Just 0d' 136 | db 0x0d, 0x0a 137 | db 0x00 138 | HelloEnd: 139 | section stack align=16 vstart=0 140 | times 128 db 0 141 | StackEnd: 142 | section end align=16 143 | ProgramEnd: -------------------------------------------------------------------------------- /第20话/Program.asm: -------------------------------------------------------------------------------- 1 | NUL equ 0x00 2 | SETCHAR equ 0x07 3 | VIDEOMEM equ 0xb800 4 | STRINGLEN equ 0xffff 5 | section head align=16 vstart=0 6 | Size dd ProgramEnd;4B 0x00 7 | SegmentAddr: 8 | CodeSeg dd section.code.start;4B 0x04 9 | DataSeg dd section.data.start;4B 0x08 10 | StackSeg dd section.stack.start;4B 0x0c 11 | SegmentNum: 12 | SegNum db (SegmentNum-SegmentAddr)/4;1B 0x10 13 | Entry dw CodeStart;2B 0x11 14 | dd section.code.start;4B 0x13 15 | 16 | section code align=16 vstart=0 17 | CodeStart: 18 | mov ax, [DataSeg] 19 | mov ds, ax 20 | mov ax, [StackSeg] 21 | mov ss, ax 22 | mov sp, StackEnd 23 | 24 | call ClearScreen 25 | call PrintLines 26 | jmp $ 27 | PrintLines: 28 | mov cx, HelloEnd-Hello 29 | xor si, si 30 | .putc: 31 | mov al, [si] 32 | inc si 33 | mov ah, 0x0e 34 | int 0x10 35 | loop .putc 36 | ret 37 | 38 | ClearScreen: 39 | mov ax, VIDEOMEM 40 | mov es, ax 41 | xor di, di 42 | mov bl, ' ' 43 | mov bh, SETCHAR 44 | mov cx, 2000 45 | .putspace: 46 | mov [es:di], bl 47 | inc di 48 | mov [es:di], bh 49 | inc di 50 | loop .putspace 51 | ret 52 | 53 | section data align=16 vstart=0 54 | Hello db 'Hello,I come from program on sector 1,loaded by bootloader!' 55 | db 0x0d, 0x0a 56 | db 'Haha,This is a new line!' 57 | db 0x0a 58 | db 'Just 0a' 59 | db 0x0d 60 | db 'Just 0d' 61 | db 0x0d, 0x0a 62 | db 0x00 63 | HelloEnd: 64 | section stack align=16 vstart=0 65 | times 128 db 0 66 | StackEnd: 67 | section end align=16 68 | ProgramEnd: -------------------------------------------------------------------------------- /第22话/32bits.asm: -------------------------------------------------------------------------------- 1 | BITS 16 2 | mov ax, 1 3 | mov eax, 1 4 | BITS 32 5 | mov ax, 1 6 | mov eax, 1 7 | BITS 64 8 | mov ax, 1 9 | mov rax, 1 -------------------------------------------------------------------------------- /第23话/BootLoader.asm: -------------------------------------------------------------------------------- 1 | ;只有一个段,从0x7c00开始 2 | section Initial vstart=0x7c00 3 | ;程序开始前的设置,先把段寄存器都置为0,后续所有地址都是相对0x00000的偏移 4 | ZeroTheSegmentRegister: 5 | xor ax, ax 6 | mov ds, ax 7 | mov es, ax 8 | mov ss, ax 9 | ;栈空间位于0x7c00及往前的空间,栈顶在0x7c00 10 | SetupTheStackPointer: 11 | mov sp, 0x7c00 12 | Start: 13 | mov si, BootLoaderStart 14 | call PrintString 15 | ;查看是否支持拓展int 13h 16 | CheckInt13: 17 | mov ah, 0x41 18 | mov bx, 0x55aa 19 | mov dl, 0x80 20 | int 0x13 21 | cmp bx, 0xaa55 22 | mov byte [ShitHappens+0x06], 0x31 23 | jnz BootLoaderEnd 24 | ;寻找MBR分区表中的活动分区,看分区项第一个字节是否为0x80,最多4个分区 25 | SeekTheActivePartition: 26 | ;分区表位于0x7c00+446=0x7c00+0x1be=0x7dbe的位置,使用di作为基地址 27 | mov di, 0x7dbe 28 | mov cx, 4 29 | isActivePartition: 30 | mov bl, [di] 31 | cmp bl, 0x80 32 | ;如果是则说明找到了,使用jmp if equel指令跳转继续 33 | je ActivePartitionFound 34 | ;如果没找到,则继续寻找下一个分区项,si+16 35 | add di, 16 36 | loop isActivePartition 37 | ActivePartitionNotFound: 38 | mov byte [ShitHappens+0x06], 0x32 39 | jmp BootLoaderEnd 40 | ;找到活动分区后,di目前就是活动分区项的首地址 41 | ActivePartitionFound: 42 | mov si, PartitionFound 43 | call PrintString 44 | ;ebx保存活动分区的起始地址 45 | mov ebx, [di+8] 46 | mov dword [BlockLow], ebx 47 | ;目标内存起始地址 48 | mov word [BufferOffset], 0x7e00 49 | mov byte [BlockCount], 1 50 | ;读取第一个扇区 51 | call ReadDisk 52 | GetFirstFat: 53 | mov di, 0x7e00 54 | ;ebx目前为保留扇区数 55 | xor ebx, ebx 56 | mov bx, [di+0x0e] 57 | ;FirstFat起始扇区号=隐藏扇区+保留扇区 58 | mov eax, [di+0x1c] 59 | add ebx, eax 60 | ;获取数据区起始区扇区号 61 | GetDataAreaBase: 62 | mov eax, [di+0x24] 63 | xor cx, cx 64 | mov cl, [di+0x10] 65 | AddFatSize: 66 | add ebx, eax 67 | loop AddFatSize 68 | ;读取数据区8个扇区/1个簇 69 | ReadRootDirectory: 70 | mov [BlockLow], ebx 71 | mov word [BufferOffset], 0x8000 72 | mov di, 0x8000 73 | mov byte [BlockCount], 8 74 | call ReadDisk 75 | mov byte [ShitHappens+0x06], 0x34 76 | SeekTheInitialBin: 77 | cmp dword [di], 'INIT' 78 | jne nextFile 79 | cmp dword [di+4], 'IAL ' 80 | jne nextFile 81 | cmp dword [di+8], 'BIN ' 82 | jne nextFile 83 | jmp InitialBinFound 84 | nextFile: 85 | cmp di, 0x9000 86 | ja BootLoaderEnd 87 | add di, 32 88 | jmp SeekTheInitialBin 89 | 90 | InitialBinFound: 91 | mov si, InitialFound 92 | call PrintString 93 | ;获取文件长度 94 | mov ax, [di+0x1c] 95 | mov dx, [di+0x1e] 96 | ;文件长度是字节为单位的,需要先除以512得到扇区数 97 | mov cx, 512 98 | div cx 99 | ;如果余数不为0,则需要多读一个扇区 100 | cmp dx, 0 101 | je NoRemainder 102 | ;ax是要读取的扇区数 103 | inc ax 104 | mov [BlockCount], ax 105 | NoRemainder: 106 | ;文件起始簇号,也是转为扇区号,乘以8即可 107 | mov ax, [di+0x1a] 108 | sub ax, 2 109 | mov cx, 8 110 | mul cx 111 | ;现在文件起始扇区号存在dx:ax,直接保存到ebx,这个起始是相对于DataBase 0x32,72 112 | ;所以待会计算真正的起始扇区号还需要加上DataBase 113 | and eax, 0x0000ffff 114 | add ebx, eax 115 | mov ax, dx 116 | shl eax, 16 117 | add ebx, eax 118 | mov [BlockLow], ebx 119 | mov word [BufferOffset], 0x9000 120 | mov di, 0x9000 121 | call ReadDisk 122 | ;跳转到Initial.bin继续执行 123 | mov si, GotoInitial 124 | call PrintString 125 | jmp di 126 | ReadDisk: 127 | mov ah, 0x42 128 | mov dl, 0x80 129 | mov si, DiskAddressPacket 130 | int 0x13 131 | test ah, ah 132 | mov byte [ShitHappens+0x06], 0x33 133 | jnz BootLoaderEnd 134 | ret 135 | 136 | ;打印以0x0a结尾的字符串 137 | PrintString: 138 | push ax 139 | push cx 140 | push si 141 | mov cx, 512 142 | PrintChar: 143 | mov al, [si] 144 | mov ah, 0x0e 145 | int 0x10 146 | cmp byte [si], 0x0a 147 | je Return 148 | inc si 149 | loop PrintChar 150 | Return: 151 | pop si 152 | pop cx 153 | pop ax 154 | ret 155 | 156 | BootLoaderEnd: 157 | mov si, ShitHappens 158 | call PrintString 159 | hlt 160 | ;使用拓展int 13h读取硬盘的结构体DAP 161 | DiskAddressPacket: 162 | ;包大小,目前恒等于16/0x10,0x00 163 | PackSize db 0x10 164 | ;保留字节,恒等于0,0x01 165 | Reserved db 0 166 | ;要读取的数据块个数,0x02 167 | BlockCount dw 0 168 | ;目标内存地址的偏移,0x04 169 | BufferOffset dw 0 170 | ;目标内存地址的段,让它等于0,0x06 171 | BufferSegment dw 0 172 | ;磁盘起始绝对地址,扇区为单位,这是低字节部分,0x08 173 | BlockLow dd 0 174 | ;这是高字节部分,0x0c 175 | BlockHigh dd 0 176 | ImportantTips: 177 | 178 | BootLoaderStart db 'Start Booting!' 179 | db 0x0d, 0x0a 180 | PartitionFound db 'Get Partition!' 181 | db 0x0d, 0x0a 182 | InitialFound db 'Get Initial!' 183 | db 0x0d, 0x0a 184 | GotoInitial db 'Go to Initial!' 185 | db 0x0d, 0x0a 186 | ShitHappens db 'Error 0, Shit happens, check your code!' 187 | db 0x0d, 0x0a 188 | ;结束为止 189 | times 446-($-$$) db 0 190 | 191 | 192 | -------------------------------------------------------------------------------- /第23话/Initial.asm: -------------------------------------------------------------------------------- 1 | section Initial align=16 vstart=0x9000 2 | EnterProtectMode: 3 | ;禁用中断先 4 | DisableInterrupt: 5 | cli 6 | SetupGDTDesc: 7 | mov ax, GDTEnd 8 | sub ax, GDTStart 9 | sub ax, 1 10 | ;GDT Limits 11 | mov [GDTStart], ax 12 | ;GDT Base 13 | mov ax, GDTStart 14 | mov [GDTStart+2], ax 15 | 16 | ;加载临时GDT 17 | LoadGDT: 18 | lgdt [GDTStart] 19 | 20 | %define SEC_DEFAULT_CR0 0x40000023 21 | %define SEC_DEFAULT_CR4 0x640 22 | 23 | EnableProtectBit: 24 | mov eax, SEC_DEFAULT_CR0 25 | mov cr0, eax 26 | jmp dword CodeDescriptor:ProtectModeLand 27 | BITS 32 28 | ProtectModeLand: 29 | mov eax, SEC_DEFAULT_CR4 30 | mov cr4, eax 31 | ResetSegmentRegister: 32 | mov ax, DataDescriptor 33 | mov ds, ax 34 | mov fs, ax 35 | mov gs, ax 36 | mov ss, ax 37 | mov ax, VideoDescriptor 38 | mov es, ax 39 | NowUnderProtected: 40 | mov esi, TipProtectedMode 41 | mov dl, 0 42 | call PrintString 43 | mov edi, 0x00008000 44 | 45 | IsLongModeSupported: 46 | mov eax, 0x80000000 47 | cpuid 48 | cmp eax, 0x80000000 49 | jbe NoLongMode 50 | mov eax, 0x80000001 51 | cpuid 52 | bt edx, 29 53 | jnc NoLongMode 54 | ;支持Long Mode,那就开启分页,进入64位 55 | YesLongMode: 56 | mov esi, TipYesLongMode 57 | mov dl, 0 58 | call PrintString 59 | ;在开启64位之前,需要定义页表 60 | ;这个参考EDKII的代码,那是经过实战的 61 | 62 | 63 | 64 | jmp InitialEnd 65 | ;不支持Long Mode/IA-32e,就按照正常的32位CPU初始化 66 | SeekTheKernelElf: 67 | cmp dword [edi], 'INIT' 68 | jne nextFile 69 | cmp dword [edi+4], 'IAL ' 70 | jne nextFile 71 | cmp dword [edi+8], 'BIN ' 72 | jne nextFile 73 | jmp KernelElfFound 74 | nextFile: 75 | cmp edi, 0x9000 76 | ja NoKernelElf 77 | add edi, 32 78 | jmp SeekTheKernelElf 79 | KernelElfFound: 80 | mov esi, TipKernelFound 81 | mov dl, 0 82 | call PrintString 83 | ;获取文件长度 84 | mov ax, [di+0x1c] 85 | mov dx, [di+0x1e] 86 | ;文件长度是字节为单位的,需要先除以512得到扇区数 87 | mov cx, 512 88 | div cx 89 | ;如果余数不为0,则需要多读一个扇区 90 | cmp dx, 0 91 | je NoRemainder 92 | ;ax是要读取的扇区数 93 | inc ax 94 | mov [BlockCount], ax 95 | NoRemainder: 96 | ;文件起始簇号,也是转为扇区号,乘以8即可 97 | mov ax, [edi+0x1a] 98 | sub ax, 2 99 | mov cx, 8 100 | mul cx 101 | ;现在文件起始扇区号存在dx:ax,直接保存到ebx,这个起始是相对于DataBase 0x32,72 102 | ;所以待会计算真正的起始扇区号还需要加上DataBase 103 | and eax, 0x0000ffff 104 | add ebx, eax 105 | mov ax, dx 106 | shl eax, 16 107 | add ebx, eax 108 | mov [BlockLow], ebx 109 | mov word [BufferOffset], 0x9000 110 | mov di, 0x9000 111 | ; call ReadDisk 112 | ;跳转到Initial.bin继续执行 113 | mov si, TipGotoKernel 114 | mov dl, 0 115 | call PrintString 116 | jmp di 117 | NoKernelElf: 118 | mov esi, TipNoKernelElf 119 | mov dl, 0 120 | call PrintString 121 | hlt 122 | NoLongMode: 123 | mov esi, TipNoLongMode 124 | mov dl, 0 125 | call PrintString 126 | jmp InitialEnd 127 | InitialEnd: 128 | hlt 129 | 130 | ;打印CPUID结果 131 | PrintCPUIDResult: 132 | push ecx 133 | call SaveCPUIDResult 134 | mov esi, CPUIDResult 135 | mov ecx, 52 136 | call PrintNBytesAscii 137 | pop ecx 138 | ret 139 | PrintCPUIDResultHex: 140 | push ecx 141 | call SaveCPUIDResult 142 | mov esi, CPUIDResult 143 | mov ecx, 4 144 | StartPrintCPUIDHex: 145 | call PrintOneRegister 146 | add esi, 13 147 | loop StartPrintCPUIDHex 148 | pop ecx 149 | ret 150 | 151 | PrintOneRegister: 152 | push ecx 153 | push esi;0 154 | mov ecx, 7 155 | call PrintNBytesAscii 156 | add esi, 10;10 157 | mov ecx, 4 158 | call PrintNBytesHexTop 159 | add esi, 1; 160 | mov ecx, 2 161 | call PrintNBytesAscii 162 | pop esi 163 | pop ecx 164 | ret 165 | ;保存CPUID指令的查询结果 166 | SaveCPUIDResult: 167 | mov [reax], eax 168 | mov [rebx], ebx 169 | mov [recx], ecx 170 | mov [redx], edx 171 | ret 172 | ;打印N个字节的16进制表示,从高到低 173 | PrintNBytesHexTop: 174 | push ax 175 | push esi 176 | StartPrintByteHexTop: 177 | mov al, [esi] 178 | call PrintByteHex 179 | dec esi 180 | loop StartPrintByteHexTop 181 | PrintNBytesHexTopEnd: 182 | pop esi 183 | pop ax 184 | ret 185 | ;打印N个字节的16进制表示 186 | PrintNBytesHex: 187 | push ax 188 | push esi 189 | StartPrintByteHex: 190 | mov al, [esi] 191 | call PrintByteHex 192 | inc esi 193 | loop StartPrintByteHex 194 | PrintNBytesHexEnd: 195 | pop esi 196 | pop ax 197 | ret 198 | ;打印AL寄存器的16进制形式 199 | PrintByteHex: 200 | push bx 201 | mov bl, al 202 | shr al, 4 203 | call PrintHalfByteHex 204 | mov al, bl 205 | and al, 0x0f 206 | call PrintHalfByteHex 207 | mov al, bl 208 | pop bx 209 | ret 210 | ;打印半个字节的Hex 211 | ;入参为al 212 | PrintHalfByteHex: 213 | push ax 214 | ;比较当前值与0x09,如果大则表示应该是A~F 215 | cmp al, 0x09 216 | ;打印一个值的Ascii 217 | ja PrintAF 218 | ;打印0~9之间的数字 219 | PrintNum: 220 | add al, 48 221 | call PrintByteAscii 222 | jmp PrintHexEnd 223 | ;打印A~F之间的字母 224 | PrintAF: 225 | add al, 55 226 | call PrintByteAscii 227 | jmp PrintHexEnd 228 | PrintHexEnd: 229 | pop ax 230 | ret 231 | ;打印普通字符串 232 | ;dl:结束符字节 233 | PrintString: 234 | push ax 235 | push cx 236 | push dx 237 | push esi 238 | mov cx, 65535 239 | StartPrintString: 240 | mov al, [esi] 241 | cmp al, dl 242 | je PrintStringEnd 243 | call PrintByteAscii 244 | inc esi 245 | loop StartPrintString 246 | PrintStringEnd: 247 | pop esi 248 | pop dx 249 | pop cx 250 | pop ax 251 | ret 252 | 253 | 254 | ;打印N个普通字符,入参为 255 | ;cx:打印的字符长度,也即N 256 | ;esi:需要打印的内存起始地址 257 | PrintNBytesAscii: 258 | push ax 259 | push cx 260 | push esi 261 | StartPrintByteAscii: 262 | mov al, [esi] 263 | call PrintByteAscii 264 | inc esi 265 | loop StartPrintByteAscii 266 | PrintNBytesAsciiEnd: 267 | pop esi 268 | pop cx 269 | pop ax 270 | ret 271 | 272 | ;打印一个普通字符,入参为al 273 | PrintByteAscii: 274 | push ax 275 | push dx 276 | push di 277 | push esi 278 | call GetCursor 279 | ;判断回车 280 | cmp al, 0x0d 281 | jz PrintCR 282 | ;判断换行 283 | cmp al, 0x0a 284 | jz PrintLF 285 | PrintNormal: 286 | mov [es:di], al 287 | inc esi 288 | add di, 2 289 | call ShouldScreenRoll 290 | call SetCursor 291 | jmp PrintByteAsciiEnd 292 | PrintCR: 293 | mov dl, 160 294 | mov ax, di 295 | div dl 296 | shr ax, 8 297 | sub di, ax 298 | call SetCursor 299 | inc esi 300 | jmp PrintByteAsciiEnd 301 | PrintLF: 302 | add di, 160 303 | call ShouldScreenRoll 304 | call SetCursor 305 | inc esi 306 | jmp PrintByteAsciiEnd 307 | PrintByteAsciiEnd: 308 | pop esi 309 | pop di 310 | pop dx 311 | pop ax 312 | ret 313 | ;判断是否需要滚动屏幕 314 | ShouldScreenRoll: 315 | cmp di, 4000 316 | ;超出屏幕,需要滚动,jae=jump if equal or above 317 | jb NoScreenroll 318 | RollScreen: 319 | push ax 320 | push cx 321 | push ds 322 | push si 323 | cld 324 | mov ax, es 325 | mov ds, ax 326 | mov si, 0xa0 327 | mov di, 0x00 328 | mov cx, 1920 329 | rep movsw 330 | mov di, 3840 331 | call ClearOneLine 332 | pop si 333 | pop ds 334 | pop cx 335 | pop ax 336 | ;不超出屏幕 337 | NoScreenroll: 338 | ret 339 | ;滚动屏幕,movsw mov from ds:si to es:di 340 | ClearOneLine: 341 | push di 342 | mov cx, 80 343 | PrintBlackSpace: 344 | mov word [es:di], 0x0720 345 | add di, 2 346 | loop PrintBlackSpace 347 | sub di, 160 348 | pop di 349 | ret 350 | 351 | GetCursor: 352 | push ax 353 | push dx 354 | mov dx,0x3d4 355 | mov al,0x0e 356 | out dx,al 357 | mov dx,0x3d5 358 | in al,dx ;高8位 359 | mov ah,al 360 | 361 | mov dx,0x3d4 362 | mov al,0x0f 363 | out dx,al 364 | mov dx,0x3d5 365 | in al,dx ;低8位 366 | add ax, ax 367 | ; mov [CursorNow], ax 368 | mov di, ax 369 | pop dx 370 | pop ax 371 | ret 372 | ;设置光标位置 373 | SetCursor: 374 | push dx 375 | push bx 376 | push ax 377 | 378 | ; mov [CursorNow], di 379 | mov ax, di 380 | mov dx, 0 381 | mov bx, 2 382 | div bx 383 | 384 | mov bx, ax 385 | mov dx, 0x3d4 386 | mov al, 0x0e 387 | out dx, al 388 | mov dx, 0x3d5 389 | mov al, bh 390 | out dx, al 391 | mov dx, 0x3d4 392 | mov al, 0x0f 393 | out dx, al 394 | mov al, bl 395 | mov dx, 0x3d5 396 | out dx, al 397 | pop ax 398 | pop bx 399 | pop dx 400 | ret 401 | 402 | ; Macros for GDT entries 403 | %define PRESENT_FLAG(p) (p << 7) 404 | %define DPL(dpl) (dpl << 5) 405 | %define SYSTEM_FLAG(s) (s << 4) 406 | %define DESC_TYPE(t) (t) 407 | 408 | ; Type: data, expand-up, writable, accessed 409 | %define DATA32_TYPE 3 410 | ; Type: execute, readable, expand-up, accessed 411 | %define CODE32_TYPE 0xb 412 | ; Type: execute, readable, expand-up, accessed 413 | %define CODE64_TYPE 0xb 414 | ; Macros for GDT defination 415 | %define GRANULARITY_FLAG(g) (g << 7) 416 | %define DEFAULT_SIZE32(d) (d << 6) 417 | %define CODE64_FLAG(l) (l << 5) 418 | %define UPPER_LIMIT(l) (l) 419 | GDTStart: 420 | ;空描述符,实际可以有比较好的用途,把gdt描述那48位放过来 421 | NullDescriptor equ $-GDTStart 422 | dw 0 ; 段界限,Limits 00 423 | dw 0 ; base:15~0 02 424 | db 0 ; base:23~16 04 425 | db 0 ; sys flag, dpl, type 05 426 | db 0 ; limit 19:16, flags 05 427 | db 0 ; base 31:24 428 | ;数据段描述符,用于字符模式下写入信息 429 | DataDescriptor equ $-GDTStart 430 | dw 0xffff ; 段界限,Limits 00 431 | dw 0 ; base:15~0 02 432 | db 0 ; base:23~16 04 433 | db PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(DATA32_TYPE) 434 | db GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf) 435 | db 0 ; base 31:24 436 | VideoDescriptor equ $-GDTStart 437 | dw 0xffff ; 段界限,Limits 00 438 | dw 0x8000 ; base:15~0 02 439 | db 0x0b ; base:23~16 04 440 | db PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(DATA32_TYPE) 441 | db GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf) 442 | db 0 ; base 31:24 443 | ;32位代码段描述符 444 | CodeDescriptor equ $-GDTStart 445 | dw 0xffff ; 段界限,Limits 00 446 | dw 0 ; base:15~0 02 447 | db 0 ; base:23~16 04 448 | db PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE) 449 | db GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf) 450 | db 0 ; base 31:24 451 | ;长模式代码段描述符 452 | LongDescriptor equ $-GDTStart 453 | dw 0xffff ; 段界限,Limits 00 454 | dw 0 ; base:15~0 02 455 | db 0 ; base:23~16 04 456 | db PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE64_TYPE) 457 | db GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(1)|UPPER_LIMIT(0xf) 458 | db 0 ; base 31:24 459 | GDTEnd: 460 | 461 | TipProtectedMode db 'Now you are under 32 bits Protected Mode!' 462 | db 0x0d, 0x0a, 0 463 | TipNoLongMode db 'No, Long Mode is not supported on this computer.' 464 | db 0x0d, 0x0a, 0 465 | TipYesLongMode db 'Yes! Long Mode is supported on this computer.' 466 | db 0x0d, 0x0a, 0 467 | TipKernelFound db 'Yes! Kernel.elf is found, good for you!' 468 | db 0x0d, 0x0a, 0 469 | TipNoKernelElf db 'Kernel.elf is not found on the disk, sad' 470 | db 0x0d, 0x0a, 0 471 | TipGotoKernel db 'Now we are going to jump to Kernel.elf, yes!' 472 | db 0x0d, 0x0a, 0 473 | DiskAddressPacket: 474 | ;包大小,目前恒等于16/0x10,0x00 475 | PackSize db 0x10 476 | ;保留字节,恒等于0,0x01 477 | Reserved db 0 478 | ;要读取的数据块个数,0x02 479 | BlockCount dw 0 480 | ;目标内存地址的偏移,0x04 481 | BufferOffset dw 0 482 | ;目标内存地址的段,让它等于0,0x06 483 | BufferSegment dw 0 484 | ;磁盘起始绝对地址,扇区为单位,这是低字节部分,0x08 485 | BlockLow dd 0 486 | ;这是高字节部分,0x0c 487 | BlockHigh dd 0 488 | ;CursorNow dw 0 489 | FlagsTip: 490 | flagtip db 'EFLAGS: ' 491 | cf db 'cf ' 492 | db 'CF ' 493 | pf db 'pf ' 494 | db 'PF ' 495 | af db 'af ' 496 | db 'AF ' 497 | zf db 'zf ' 498 | db 'ZF ' 499 | sf db 'sf ' 500 | db 'SF ' 501 | tf db 'tf ' 502 | db 'TF ' 503 | if db 'if ' 504 | db 'IF ' 505 | df db 'df ' 506 | db 'DF ' 507 | of db 'of ' 508 | db 'OF ' 509 | CPUIDResult: 510 | teax db 'EAX: 0x';0x00 511 | reax dd 0 ;0x07 512 | db ' ';0x11 513 | tebx db 'EBX: 0x' 514 | rebx dd 0 515 | db ' ' 516 | tecx db 'ECX: 0x' 517 | recx dd 0 518 | db ' ' 519 | tedx db 'EDX: 0x' 520 | redx dd 0 521 | db 0x0d, 0x0a 522 | 523 | 524 | -------------------------------------------------------------------------------- /第27话/SimpleInitialL.asm: -------------------------------------------------------------------------------- 1 | section Initial align=16 vstart=0x9000 2 | mov si, InitialLandHere 3 | call PrintString 4 | jmp InitialEnd 5 | ;打印以0x0a结尾的字符串 6 | PrintString: 7 | push ax 8 | push cx 9 | push si 10 | mov cx, 512 11 | PrintChar: 12 | mov al, [si] 13 | mov ah, 0x0e 14 | int 0x10 15 | cmp byte [si], 0x0a 16 | je Return 17 | inc si 18 | loop PrintChar 19 | Return: 20 | pop si 21 | pop cx 22 | pop ax 23 | ret 24 | InitialEnd: 25 | hlt 26 | InitialLandHere db 'I come from Initial.bin!' 27 | db 0x0d, 0x0a -------------------------------------------------------------------------------- /第43话/sms.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define TRUE 1 5 | #define MAXCMD 16 //最大命令长度 6 | #define MAXDATA 1024 //最大数据长度 7 | 8 | #define INSERT 1 //插入数据 9 | #define SEARCH 2 //搜索数据 10 | #define UPDATE 3 //修改数据 11 | #define DELETE 4 //删除数据 12 | #define SAVE 5 //保存数据 13 | #define HELP 6 //帮助命令 14 | #define SHOW 7 //显示数据 15 | #define QUIT 0 //退出命令 16 | #define ILLEGAL -1 //非法指令 17 | 18 | int getopcode(char* command); 19 | int help(); 20 | int show(); 21 | int save(); 22 | int insert(char* data); 23 | int search(char* data); 24 | int update(char* data); 25 | int delete(char* data); 26 | 27 | int main(int argc, char* argv[]) 28 | { 29 | int opcode = ILLEGAL; 30 | char command[MAXCMD] = {0}; //用于接收命令 31 | char data[MAXDATA] = {0}; //用于接收数据 32 | 33 | while(TRUE) //无限循环 34 | { 35 | printf("sms>"); //输出提示符 36 | scanf("%s", command); //输入命令 37 | opcode = getopcode(command); //获取opcde 38 | if(opcode == ILLEGAL) 39 | { 40 | printf("Unsupported command!\n"); 41 | continue; 42 | } 43 | if(opcode == QUIT) 44 | { 45 | printf("Bye!\n"); 46 | return 0; 47 | } 48 | if(opcode == HELP) 49 | { 50 | help(); 51 | continue; 52 | } 53 | if(opcode == SHOW) 54 | { 55 | show(); 56 | continue; 57 | } 58 | if(opcode == SAVE) 59 | { 60 | save(); 61 | continue; 62 | } 63 | scanf("%s", data); //用于输入数据 64 | switch(opcode) 65 | { 66 | case INSERT: insert(data); break; 67 | case SEARCH: search(data); break; 68 | case UPDATE: update(data); break; 69 | case DELETE: delete(data); break; 70 | } 71 | } 72 | return 0; 73 | } 74 | 75 | int getopcode(char* command) 76 | { 77 | int opcode = ILLEGAL; //默认指令非法 78 | if(strcmp(command, "insert") == 0) //command与"insert"比较 79 | opcode = INSERT; //结果为0则两字符串相同 80 | if(strcmp(command, "search") == 0) 81 | opcode = SEARCH; 82 | if(strcmp(command, "update") == 0) 83 | opcode = UPDATE; 84 | if(strcmp(command, "delete") == 0) 85 | opcode = DELETE; 86 | if(strcmp(command, "save") == 0) 87 | opcode = SAVE; 88 | if(strcmp(command, "help") == 0) 89 | opcode = HELP; 90 | if(strcmp(command, "quit") == 0) 91 | opcode = QUIT; 92 | if(strcmp(command, "show") == 0) 93 | opcode = SHOW; 94 | return opcode; 95 | } 96 | int help() 97 | { 98 | printf("Help\n"); 99 | return 0; 100 | } 101 | int show() 102 | { 103 | printf("Show\n"); 104 | return 0; 105 | } 106 | int save() 107 | { 108 | printf("Save\n"); 109 | return 0; 110 | } 111 | int insert(char* data) 112 | { 113 | printf("Insert data %s\n", data); 114 | return 0; 115 | } 116 | int search(char* data) 117 | { 118 | printf("Search data %s\n", data); 119 | return 0; 120 | } 121 | int update(char* data) 122 | { 123 | printf("Update data %s\n", data); 124 | return 0; 125 | } 126 | int delete(char* data) 127 | { 128 | printf("Delete data %s\n", data); 129 | return 0; 130 | } -------------------------------------------------------------------------------- /第44话/sms.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define TRUE 1 6 | #define MAXSTUS 10 7 | #define MAXCMD 16 //最大命令长度 8 | #define MAXNAME 32 //最大姓名长度 9 | #define MAXDATA 1024 //最大数据长度 10 | #define CODELEN 8 //学号长度 11 | 12 | #define INSERT 1 //插入数据 13 | #define SEARCH 2 //搜索数据 14 | #define UPDATE 3 //修改数据 15 | #define DELETE 4 //删除数据 16 | #define SAVE 5 //保存数据 17 | #define HELP 6 //帮助命令 18 | #define SHOW 7 //显示数据 19 | #define QUIT 0 //退出命令 20 | #define ILLEGAL -1 //非法指令 21 | #define ERROR -2 //一般错误 22 | 23 | typedef struct student 24 | { 25 | unsigned int code; 26 | char name[MAXNAME]; 27 | }Student; 28 | 29 | int getopcode(char* command); 30 | int help(); 31 | int show(); 32 | int save(Student* stu, int index); 33 | int insert(char* data, Student* stu); 34 | int search(char* data); 35 | int update(char* data); 36 | int delete(char* data); 37 | 38 | int main(int argc, char* argv[]) 39 | { 40 | int opcode = ILLEGAL; 41 | int index = 0; 42 | char command[MAXCMD] = {0}; //用于接收命令 43 | char data[MAXDATA] = {0}; //用于接收数据 44 | Student stus[MAXSTUS]; 45 | Student* stu = stus; 46 | 47 | while(TRUE) //无限循环 48 | { 49 | printf("sms>"); //输出提示符 50 | scanf("%s", command); //输入命令 51 | opcode = getopcode(command); //获取opcde 52 | if(opcode == ILLEGAL) 53 | { 54 | printf("Unsupported command!\n"); 55 | continue; 56 | } 57 | if(opcode == QUIT) 58 | { 59 | printf("Bye!\n"); 60 | return 0; 61 | } 62 | if(opcode == HELP) 63 | { 64 | help(); 65 | continue; 66 | } 67 | if(opcode == SHOW) 68 | { 69 | show(); 70 | continue; 71 | } 72 | if(opcode == SAVE) 73 | { 74 | save(stu, index); 75 | continue; 76 | } 77 | scanf("%s", data); //用于输入数据 78 | switch(opcode) 79 | { 80 | case INSERT: 81 | { 82 | if(index == MAXSTUS - 1) 83 | { 84 | save(stu, index); 85 | index = 0; 86 | stu = stus; 87 | } 88 | printf("Berfore insert code = %d, name = %s\n", stus[index].code, stus[index].name); 89 | insert(data, stu); 90 | printf("After insert code = %d, name = %s\n", stus[index].code, stus[index].name); 91 | index++; 92 | stu++; 93 | break; 94 | } 95 | case SEARCH: search(data); break; 96 | case UPDATE: update(data); break; 97 | case DELETE: delete(data); break; 98 | } 99 | 100 | } 101 | return 0; 102 | } 103 | 104 | int getopcode(char* command) 105 | { 106 | int opcode = ILLEGAL; //默认指令非法 107 | if(strcmp(command, "insert") == 0) //command与"insert"比较 108 | opcode = INSERT; //结果为0则两字符串相同 109 | if(strcmp(command, "search") == 0) 110 | opcode = SEARCH; 111 | if(strcmp(command, "update") == 0) 112 | opcode = UPDATE; 113 | if(strcmp(command, "delete") == 0) 114 | opcode = DELETE; 115 | if(strcmp(command, "save") == 0) 116 | opcode = SAVE; 117 | if(strcmp(command, "help") == 0) 118 | opcode = HELP; 119 | if(strcmp(command, "quit") == 0) 120 | opcode = QUIT; 121 | if(strcmp(command, "show") == 0) 122 | opcode = SHOW; 123 | return opcode; 124 | } 125 | int help() 126 | { 127 | printf("Help\n"); 128 | return 0; 129 | } 130 | int show() 131 | { 132 | printf("Show\n"); 133 | return 0; 134 | } 135 | int save(Student* stu, int index) 136 | { 137 | printf("Save\n"); 138 | FILE* datafile = fopen("data.txt", "a"); 139 | stu = stu - index; 140 | for(int i = 0; i < index; i++) 141 | { 142 | fprintf(datafile, "%d,", stu->code); 143 | fprintf(datafile, "%s\n", stu->name); 144 | stu++; 145 | } 146 | fclose(datafile); 147 | return 0; 148 | } 149 | 150 | 151 | 152 | int insert(char* data, Student* pstu) 153 | { 154 | printf("Insert data %s\n", data); 155 | char acode[CODELEN] = {0}; 156 | char aname[MAXNAME] = {0}; 157 | int i = 0; 158 | for(i = 0; i < CODELEN; i++) 159 | { 160 | if(data[i] < '0' || data[i] > '9') 161 | { 162 | printf("Please check Input with code.\n"); 163 | return ERROR; 164 | } 165 | 166 | acode[i] = data[i]; 167 | } 168 | pstu->code = atoi(acode); 169 | 170 | if(data[i] != ',') 171 | { 172 | printf("Please check input with \','\n"); 173 | return ERROR; 174 | } 175 | i++; 176 | while((data[i] >= 'a' && data[i] <= 'z') || (data[i] >= 'A' && data[i] <= 'Z')) 177 | { 178 | pstu->name[i-CODELEN - 1] = data[i]; 179 | i++; 180 | } 181 | 182 | if(data[i] == '\0') 183 | { 184 | pstu->name[i-CODELEN] = data[i]; 185 | return 0; 186 | } 187 | else 188 | { 189 | printf("Please check input with name.\n"); 190 | return ERROR; 191 | } 192 | } 193 | 194 | 195 | 196 | int search(char* data) 197 | { 198 | printf("Search data %s\n", data); 199 | return 0; 200 | } 201 | int update(char* data) 202 | { 203 | printf("Update data %s\n", data); 204 | return 0; 205 | } 206 | int delete(char* data) 207 | { 208 | printf("Delete data %s\n", data); 209 | return 0; 210 | } -------------------------------------------------------------------------------- /第45话/list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAXNAME 32 //最大姓名长度 6 | #define GPERROR -1 7 | #define SUCESS 0 8 | 9 | typedef struct student 10 | { 11 | unsigned int code; 12 | char name[MAXNAME]; 13 | struct student *next; 14 | }Student; 15 | 16 | typedef struct stulist 17 | { 18 | Student *head; 19 | int count; 20 | }StuList; 21 | 22 | Student *createStudent() 23 | { 24 | Student *stu = (Student *)malloc(sizeof(Student)); 25 | if(stu != NULL) 26 | { 27 | stu->code = 0; 28 | memset(stu->name, 0, MAXNAME); 29 | stu->next = NULL; 30 | return stu; 31 | } 32 | return NULL; 33 | } 34 | int main(int argc, char* argv[]) 35 | { 36 | StuList stul; 37 | Student* stu; 38 | stul.head = createStudent(); 39 | if(stul.head == NULL) 40 | return GPERROR; 41 | stul.count = 1; 42 | stu = stul.head; 43 | scanf("%d,%s", &stu->code, stu->name); 44 | stu->next = createStudent(); 45 | if(stu->next == NULL) 46 | return GPERROR; 47 | stul.count++; 48 | stu = stu->next; 49 | scanf("%d,%s", &stu->code, stu->name); 50 | stu = stul.head; 51 | for(int i = 0; i < stul.count; i++) 52 | { 53 | printf("StuList[%d]`s code is %d, name is %s\n", i, stu->code, stu->name); 54 | stu = stu->next; 55 | } 56 | return SUCESS; 57 | } -------------------------------------------------------------------------------- /第46话/blue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #define DEV_PATH "/dev/input/event20" //difference is possible 10 | #define L 1 11 | #define R 2 12 | #define U 3 13 | #define D 4 14 | int main() 15 | { 16 | int event_file = 0; 17 | int keynum = 0; 18 | struct input_event event_in; 19 | 20 | while(1) 21 | { 22 | if(event_file <= 0) 23 | { 24 | event_file = open(DEV_PATH, O_RDONLY); 25 | continue; 26 | } 27 | 28 | if (read(event_file, &event_in, sizeof(event_in)) != sizeof(event_in)) 29 | { 30 | continue; 31 | } 32 | 33 | if (event_in.type == EV_ABS) 34 | { 35 | if (event_in.code == 16) 36 | { 37 | if (event_in.value == -1) 38 | { 39 | printf("方向 左左 按下\n"); 40 | keynum = L; 41 | } 42 | 43 | if (event_in.value == 0 && keynum == L) 44 | { 45 | printf("方向 左左 抬起\n"); 46 | } 47 | 48 | if (event_in.value == 1) 49 | { 50 | printf("方向 右右 按下\n"); 51 | keynum = R; 52 | } 53 | 54 | if (event_in.value == 0 && keynum == R) 55 | { 56 | printf("方向 右右 抬起\n"); 57 | } 58 | } 59 | 60 | if (event_in.code == 17) 61 | { 62 | if (event_in.value == -1) 63 | { 64 | printf("方向 上上 按下\n"); 65 | keynum = U; 66 | } 67 | 68 | if (event_in.value == 0 && keynum == U) 69 | { 70 | printf("方向 上上 抬起\n"); 71 | } 72 | 73 | if (event_in.value == 1) 74 | { 75 | printf("方向 下下 按下\n"); 76 | keynum = D; 77 | } 78 | 79 | if (event_in.value == 0 && keynum == D) 80 | { 81 | printf("方向 上上 抬起\n"); 82 | } 83 | } 84 | 85 | } 86 | 87 | } 88 | return 0; 89 | } -------------------------------------------------------------------------------- /第46话/list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAXNAME 32 //最大姓名长度 6 | #define GPERROR -1 7 | #define SUCESS 0 8 | 9 | typedef struct student 10 | { 11 | unsigned int code; 12 | char name[MAXNAME]; 13 | struct student *next; 14 | }Student; 15 | 16 | typedef struct stulist 17 | { 18 | Student *head; 19 | int count; 20 | }StuList; 21 | 22 | Student *createStudent() 23 | { 24 | Student *stu = (Student *)malloc(sizeof(Student)); 25 | if(stu != NULL) 26 | { 27 | stu->code = 0; 28 | memset(stu->name, 0, MAXNAME); 29 | stu->next = NULL; 30 | return stu; 31 | } 32 | return NULL; 33 | } 34 | int main(int argc, char* argv[]) 35 | { 36 | StuList stul; 37 | Student* stu; 38 | stul.head = createStudent(); 39 | if(stul.head == NULL) 40 | return GPERROR; 41 | stul.count = 1; 42 | stu = stul.head; 43 | scanf("%d,%s", &stu->code, stu->name); 44 | stu->next = createStudent(); 45 | if(stu->next == NULL) 46 | return GPERROR; 47 | stul.count++; 48 | stu = stu->next; 49 | scanf("%d,%s", &stu->code, stu->name); 50 | stu = stul.head; 51 | FILE* datafile = fopen("data.txt", "a"); 52 | for(int i = 0; i < stul.count; i++) 53 | { 54 | printf("StuList[%d]`s code is %d, name is %s\n", i, stu->code, stu->name); 55 | fprintf(datafile, "%d,%s\n", stu->code, stu->name); 56 | stu = stu->next; 57 | } 58 | fclose(datafile); 59 | return SUCESS; 60 | } --------------------------------------------------------------------------------