我是C的新手,它是继Java之后的第二种高级编程语言.我已经掌握了大部分基础知识,但无论出于何种原因,我无法将单个字符写入屏幕内存.
该程序使用Turbo C for DOS编译,运行速度为120mhz的Am486-DX4-100.该显卡是使用Trio32芯片的非常标准的VLB Diamond Multimedia Stealth SE.
对于操作系统,我运行的PC-DOS 2000加载了ISO代码页.我正在使用标准的MDA/CGA/EGA/VGA 80列文本模式运行.
这是我编写的程序:
#include <stdio.h>
int main(void) {
unsigned short int *Video = (unsigned short int *)0xB8000;
*Video = 0x0402;
getchar();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
正如我所说,我对C很新,所以如果我的错误显而易见,我道歉,我无法找到一个可以理解的如何做到这一点的可靠来源.
据我所知,在x86平台上的实模式下,文本模式的屏幕内存从0xB8000开始.每个字符存储在两个字节中,一个用于字符,一个用于背景/前景.我的想法是将值0x0402(应该是一个红色的笑脸)写入0xB8000.这应该放在屏幕的左上角.
我已经考虑了屏幕可能滚动的可能性,因此在执行时会立即以两种方式删除我的角色.要解决此问题,我尝试过:
我可以读取并打印我写入内存的值,所以它显然仍然在内存中,但无论出于何种原因,我都没有在屏幕上显示任何内容.我显然做错了,但我不知道会出现什么问题.如果需要任何其他细节,请询问.感谢您提供任何可能的帮助.
我正在读关于内存寻址的内容.我读了关于段偏移然后关于描述符偏移的内容.我知道如何计算实模式下的确切地址.这一切都没问题,但我无法理解究竟是什么偏移?到处都读到:
在实模式下,寄存器只有16位,因此最多只能寻址64k.为了允许寻址更多内存,地址קד是从segment*16 + offset计算的.
在这里我可以理解第一行.我们有16位,所以我们可以解决最多2 ^ 16 = 64k.
但这第二行是什么?细分代表什么?为什么我们将它乘以16?为什么我们添加偏移.我只是无法理解这个偏移是什么?有人可以解释我或给我链接吗?
我正在努力将uc/OS-II从DOS移植到x86(实模式).我需要:
__PRE__
我想知道是否有任何工具链可以做到这一点.
非常感谢
在x86的实模式中,需要使用哪些指令在多处理器系统中的不同处理器上运行代码?
(我正在汇编程序中编写一些需要设置某些CPU寄存器的预启动代码,并在实际操作系统启动之前在系统中的每个CPU上执行此操作.)
在研究一些简单的os源代码时,我对一个简单的汇编问题感到困惑.
在这个网站:http://wiki.osdev.org/Babystep7下面的代码是从实模式切换到保护模式
mov eax, cr0
or al,1
mov cr0, eax
Run Code Online (Sandbox Code Playgroud)
我知道如何从实模式切换到保护模式.
但我的问题是,由于程序仍处于实模式,它如何使用32位寄存器或指令?
是否可以在实模式下使用32位寄存器/指令?
我目前正在boot.s源代码中读取第一个Linux内核的文件(假设0.01确实是第一个公开发布).
我知道C和ASM,后者比前者少得多.即便如此,我似乎能够理解并基本上掌握源文件中的代码.
这个文件让我很困惑.我现在意识到这是因为它处于实模式,而不是保护模式.不用说,我以前从未见过以实模式编写的ASM代码.保护模式是在我出生之前运行的事实模式x86操作系统,所以这是可以预料的.
这是我想要更好地理解的例程:
/*
* This procedure turns off the floppy drive motor, so
* that we enter the kernel in a known state, and
* don't have to worry about it later.
*/
kill_motor:
push dx
mov dx,#0x3f2
mov al,#0
outb
pop dx
ret
Run Code Online (Sandbox Code Playgroud)
向上看outb,我发现它用于将字节传递给计算机上的端口.我将基于C文档猜测这个场景将"stop motor"字节作为第一个参数传递,并将软盘驱动器端口号作为第二个参数.
这个界面是BIOS提供的吗?还是直接通过软驱?我假设BIOS对所有基本设备的基本操作都有节俭的"驱动程序".
这就是我难倒的地方:似乎数字之类的东西#0x3f2正在被掏出来.它们显然是硬件端口号或其他东西.这个文件上撒有这样的数字,没有解释他们所指的是什么.在哪里可以找到一个全面的参考资料,显示他们可以从实模式接收的所有硬件端口和控制编号?此外,似乎文件在整个启动过程中使用硬编码的内存地址在内存中移动内核.在哪里可以找到有关在实模式下可以写入哪些内存地址范围的指南?
我还阅读了Linus关于重新编程中断的评论,以避免BIOS和内部硬件中断之间的冲突.我不会撒谎,这是我的头脑.
帮助会很棒; 谷歌似乎很少涉及这个话题,万一你想知道.
我正在尝试用 C 语言对实模式 MS-DOS 进行编程。使用一些关于游戏编程的旧书作为起点。书中的源代码是为 Microsoft C 编写的,但我试图让它在 OpenWatcom v2 下编译。当我尝试访问指向 VGA 视频内存开头的指针时,我很早就遇到了问题。
#include <stdio.h>
#include <dos.h>
void Set_Video_Mode(int mode) {
union REGS inregs, outregs;
inregs.h.ah = 0;
inregs.h.al = (unsigned char) mode;
int86(0x10, &inregs, &outregs);
}
int main(void)
{
Set_Video_Mode(0x13);
//the following line throws an error, without it the code compiles and runs
char far *video_buffer = (char far *)0xA0000000L;
while (!kbhit()) { };
Set_Video_Mode(0x03);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是远指针赋值引发以下错误:
VGA.C(33):错误!E1077:缺少 '}'
VGA.C(33):警告!W107:缺少函数“main”的返回值
VGA.C(36):错误!E1099: 语句必须位于函数内部。可能的原因:缺少{
这有点令人困惑,似乎宏定义出了问题,或者是什么......
当我使用相同的编译器尝试维基百科关于远指针的文章中的代码时:
#include …Run Code Online (Sandbox Code Playgroud) 我创建了简单的代码来从硬盘驱动器加载第二个扇区,然后写入整个屏幕,空格为红色背景.问题是我总是用@符号代替空格.这是代码:
org 0x7C00
bits 16
xor ax,ax
mov ds,ax
mov es,ax
mov bx,0x8000
cli
mov ss,bx
mov sp,ax
sti
cld
clc
xor ah,ah
int 0x13
mov bx,0x07E0
mov es,bx
xor bx,bx
mov ah,0x2 ;function
mov al,0x5 ;sectors to read
mov ch,0x0 ;track
mov cl,0x2 ;sector
mov dh,0x0 ;head
int 0x13
;jc error
;mov ah, [0x7E00]
;cmp ah,0x0
;je error
jmp error
cli
hlt
jmp 0x07E0:0x0000
error:
xor bx,bx
mov ax,0xb800
mov es,ax
mov al,0x40 ;colour
mov ah,' ' ;character
.red: …Run Code Online (Sandbox Code Playgroud) 我一直在开发一个简单的引导加载程序,并且在某些环境中偶然发现问题,这些环境中的指令不起作用:
mov si, call_tbl ; SI=Call table pointer
call [call_tbl] ; Call print_char using near indirect absolute call
; via memory operand
call [ds:call_tbl] ; Call print_char using near indirect absolute call
; via memory operand w/segment override
call near [si] ; Call print_char using near indirect absolute call
; via register
Run Code Online (Sandbox Code Playgroud)
这些中的每一个碰巧涉及间接接近CALL到绝对存储器偏移.我发现如果我使用类似的JMP表,我会遇到问题.相对的呼叫和跳转似乎没有受到影响.像这样的代码有效:
call print_char
Run Code Online (Sandbox Code Playgroud)
我已经通过海报讨论了Stackoverflow上提出的建议,讨论了编写引导加载程序的注意事项.特别是我看到这个Stackoverflow回答了一般的Bootloader技巧.第一个提示是:
- 当BIOS跳转到您的代码时,您不能依赖具有有效或预期值的CS,DS,ES,SS,SP寄存器.应在引导加载程序启动时正确设置它们.您只能保证将从物理地址0x07c00加载并运行引导加载程序,并将引导驱动器号加载到DL寄存器中. …