标签: x86-16

16 位 x86 MS-DOS 实模式下的分段远指针分配

我正在尝试用 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)

c dos real-mode watcom x86-16

9
推荐指数
1
解决办法
867
查看次数

为什么CMP(比较)有时会在8086汇编中设置进位标志?

我一直在阅读并使用8086指令集,它说CMP(比较)可以设置进位标志.我知道比较会减去两个操作数,但我想知道是否有人可以在这种情况下提供一个例子.

我只是无法掌握添加数字和负数的想法会设置进位标志.我已经阅读了借旗,但我只需要一个例子来澄清我对比较指令的理解.

另外,据我所知,如果3 - 5 = -2会设置负标志...何时进位?

assembly subtraction x86-16

8
推荐指数
1
解决办法
2万
查看次数

RCR和ROR有什么区别?

我理解RCR将从右到左旋转位的术语,从进位中取出位,同时ROR将位从右向左旋转,从右侧取位,但这是它们之间的唯一区别吗?如果是这样,两条指令似乎都做同样的工作.请帮忙.谢谢

assembly x86-16

8
推荐指数
2
解决办法
2万
查看次数

为什么MS-DOS不初始化DS和ES寄存器?

为什么DSES寄存器的初始化必须由程序员手动完成?

例如:

MOV AX, DTSEG
MOV DS, AX
Run Code Online (Sandbox Code Playgroud)

另一方面,CSSS寄存器由操作系统(in MS-DOS)初始化.为什么会这样?

assembly dos intel masm x86-16

8
推荐指数
1
解决办法
1471
查看次数

如何在汇编语言8086中设置1秒的时间延迟

我的问题是我编写了一个代码,该代码应该将结果输出到连接到并行端口的一组LED中.当我运行代码时它几乎没有做任何事情.我的导师告诉我,代码运行得太快,我的眼睛看不到发生了什么.

我发现有几种方法可以延迟时间,我试图循环NOP,但我认为我无法确定发生了什么.有没有更好的方法?

我在这里有一部分代码,我必须添加一个时间延迟:

org 100h

mov ax, 0
mov dx, 378
out dx, ax
mov ax, 1  

; 1st

mov cx, 1ah
start1st:
mov ax, 1
left:
out dx, ax 
; --------------------------------> how to loop?
mov bx, 2
mul bx
cmp ax, 80h
jl left
dec cx
cmp cx,0
jg start1st
; end 1st 
Run Code Online (Sandbox Code Playgroud)

time assembly delay x86-16

8
推荐指数
3
解决办法
7万
查看次数

我应该为Intel 8086 DOS程序集使用什么代码框架?

在学习了英特尔8080结构后,我现在正在尝试学习英特尔8086以及这里的程序如何布局.就目前而言,即使查看基本示例也是非常令人生畏的,更糟糕​​的是,我无法区分两种编写8086代码的方法,我偶然发现了.也就是说,有时候我会看到:

.model small
.stack 100h
.code

start:

mov dl, ‘a’ ; store ascii code of ‘a’ in dl
mov ah, 2h ; ms-dos character output function
int 21h ; displays character in dl register
mov ax, 4c00h ; return to ms-dos
int 21h

end start
Run Code Online (Sandbox Code Playgroud)

虽然我也发现:

Progr           segment
                assume  cs:Progr, ds:dataSeg, ss:stackSeg

start:          mov     ax,dataSeg
                mov     ds,ax
                mov     ax,stackSeg
                mov     ss,ax
                mov     sp,offset top


            mov     ah,4ch
            mov     al,0
            int     21h
Progr           ends

dataSeg            segment

dataSeg            ends

stackSeg          segment
                dw    100h …
Run Code Online (Sandbox Code Playgroud)

x86 assembly dos x86-16

8
推荐指数
1
解决办法
1474
查看次数

如何用C语言编写linux启动代码?

我是学习OS开发的新手.从我读过的书中,它说启动加载器会将第一个MBR复制到0x7c00,然后从实模式开始.

并且,示例从16位汇编代码开始.但是,当我查看今天的linux内核时,arch/x86/boot有'header.S'和'boot.h',但实际代码是在main.c中实现的.

这似乎对"不编写汇编"很有用.但是,这是如何在Linux中专门完成的?我可以粗略地想象可能有特殊gcc选项和链接策略,但我看不到细节.

c assembly linux-kernel bootloader x86-16

8
推荐指数
1
解决办法
805
查看次数

在手动编码的远程调用之后定义在调试中出现的字节

我无法让MASM接受写成的远程调用指令call 0f000h:1260h,可能是因为这个问题带来的问题.

我没有乱用神秘的MASM指令,而是决定使用DB手动将其编码到我的程序中,如下所示:

pushf                      ;IRET will be executed, push flags.
db 9ah,60h,12h,0,0f0h      ;call location f000:1260.
                           ;Location pointed to by int 1c (System timer tick)
                           ;BIOS defaults it to a dummy IRET
Run Code Online (Sandbox Code Playgroud)

在使用DEBUG.COM跟踪程序时,我注意到在执行调用指令后出现"DB FE".但是,执行时不会发生这种情况int 1ch.跳转到位置f000:1260的这两种方法有什么区别?

在此输入图像描述

我假设DEBUG没有将0xfe(以及后面的字节)识别为有效的操作码.我倾倒了位置f000:1260以查看哪些字节存在.

在此输入图像描述

确实存在字节0xfe以及其他一些字节.我知道0xcf本身就是IRET的操作码(这是我期望找到的所有),那么这些其他字节是什么?

这是int 1ch位于0000:0070 的IVT条目.

在此输入图像描述

UPDATE

正如Michael Petch在他的回答中所说,奇怪的字节构成了DOSBox的回调机制.我很想知道如果我试图在我的主程序中执行这个回调会发生什么.

执行:

xor ah, ah                 ;select set video mode function
mov al, 13h                ;320x200 256 colors
db 0feh,38h,18h,00h        ;set video mode DOSBox callback.
                           ;Nothing pushed to stack.
Run Code Online (Sandbox Code Playgroud)

似乎与执行完全相同:

xor ah, ah …
Run Code Online (Sandbox Code Playgroud)

x86 assembly interrupt dosbox x86-16

8
推荐指数
1
解决办法
144
查看次数

PC启动:dl注册和驱动器号

我在互联网的某个地方读到,在跳到0x7c00之前,BIOS加载到启动设备的"驱动器号"%dl.但这个"驱动器号码"是什么?连接到计算机的每台设备都由BIOS分配了一个号码?如果是这样,我怎么知道分配给哪个设备的号码?

读取我在%dl设置了位0x80和0x70时发现的GRUB源代码,它用0x80覆盖整个寄存器.这是为什么?这是代码:

jmp 3f      /* grub-setup may overwrite this jump */
testb $0x80, %dl
jz 2f
3:
/* Ignore %dl different from 0-0x0f and 0x80-0x8f.  */
testb $0x70, %dl
jz 1f
2:     
movb $0x80, %dl
1:
Run Code Online (Sandbox Code Playgroud)

顺便说说.网络上的PC启动过程是否有详细的资源?特别是在将控件提供给引导加载程序之前BIOS的作用以及用于与之通信的标准代码(如"驱动器数").我希望编写自己的引导加载程序,我发现的所有内容都过于模糊,技术性不足以告知我的引导加载程序开始运行时计算机的确切状态.

x86 assembly bios bootloader x86-16

7
推荐指数
1
解决办法
2684
查看次数

为什么MOV不能将两个操作数都作为内存位置?

我读到该MOV指令不能为其两个操作数都有内存位置.

喜欢:MOV [0012H], [0016H]不允许.

为什么这样?

其他指令可以为其两个操作数设置内存位置吗?

assembly x86-16

7
推荐指数
1
解决办法
2887
查看次数

标签 统计

x86-16 ×10

assembly ×9

dos ×3

x86 ×3

bootloader ×2

c ×2

bios ×1

delay ×1

dosbox ×1

intel ×1

interrupt ×1

linux-kernel ×1

masm ×1

real-mode ×1

subtraction ×1

time ×1

watcom ×1