如何在C语言中使用int86函数和REGS结构为8086读取和显示文件数据
我有一个文本文件,其中包含一些内容,我必须将光标从相对转移到BOF,并使用INT 21H/42H. 在屏幕上显示其内容 这是我正在处理的代码.我正在使用VM中的Windows 98(16位DOS),它是我的系统编程分配的一部分,因此我必须使用DOSBOX中的Turbo C ++尝试使用它,但它有一些问题. 在打印上 buff 它显示随机值 代码 #include #include #include #include #include unsigned int handle; char buff[50]; void main(){ union REGS regs; // set pointer union REGS regs_r; // read file handle = open("text.txt", O_RDONLY);
12 2024-04-10
编程技术问答社区
使用Freedos是否允许我的程序访问超过64 K的内存?
我有兴趣在Freedos的C上编程,同时在此过程中学习一些基本的ASM时,是否会允许我的程序访问超过标准的640K内存? ,其次,关于ASM,我知道在现代处理器上,由于CPU架构的复杂性,很难在组装上编程,但是使用Freedos是否将我限制为可能更简单的16位指令集? 解决方案 没有任何扩展器的程序可以在DOS中使用最大的640kb低内存.但是每个结构将仅限于一个段的大小或64kb.这意味着您可以拥有10个大小64kb的大阵列.当然,您可以在一个段中有多个阵列,但是它们的总尺寸不得超过细分市场的大小.一些编译器还自动处理跨越多个部分的地址,以便您可以无缝使用大于64kb的对象,或者如果您在汇编中写作,也可以执行相同的操作 要访问更多内存,您需要一个扩展器,例如关于组装,您可以在16位模式下使用32位寄存器.有66h和67h的前缀可以更改操作数尺寸.但是,这并不意味着编写16位代码更容易.实际上,它有很多特质值得记住,例如记忆地址中的有限注册使用情况. 32位X86指令
18 2024-04-09
编程技术问答社区
解释一下AF标志在X86指令中是如何工作的?
我有一个小8086仿真器,现在有一个长时间的错误,大约两年了,AF在子内部的行为不正确并添加说明. 我当前计算其值的方式是8位数字和减法: uint8_t base=... , subt=... base=base&0xF; subt=subt&0xF; //isolate bottom nibble if((int16_t)base-subt>7 || (int16_t)base-subt7 || base+adder
16 2024-04-08
编程技术问答社区
英特尔8086汇编程序从C语言调用
我需要制定一个用于汇编语言的过程,并从C语言调用该过程(传递字符串并返回整数值).我的组装程序可以很好地"独立".我需要将它们连接在一起的帮助. 程序应该在Intel 8086上运行.我需要将MASM或EMU8086用作汇编器/模拟器.请推荐一个C编译器,也是一种制作能够调用汇编过程并获取返回值的简单C程序的方法. 如何将字符串传递给此外部功能? 如何连接ASM文件和C文件? (编译器将如何知道此过程的定义/代码在哪里?) 如何以汇编语言从C发送字符串,以及如何将整数返回到C? 解决方案 推荐C编译器 没有足够的信息,但是,如果您的平台足够重要,那么GCC已经支持它. 以及一种制作能够调用汇编过程并获取返回值的简单C程序的方法. 编写简单C程序的方式是使用文本编辑器. (哦,等等,您对代码感兴趣?在这里: #include extern int foo(); int main() { int i = fo
22 2024-04-07
编程技术问答社区
如何防止我在键盘上按键时出现重复的字符
我正在尝试学习如何防止键盘将多个字符发送到屏幕和DOS下的scanf.我正在使用涡轮-C与内联装配. 如果在键盘上输入的字符为: mmmmmmmmmyyyyy nnnnnnaaaaaammmmmmmmmmeeeeeeeeeeeeeeeiissss hhhaaaaiiiiimmmm 在控制台上看到的字符和scanf处理的字符将是: 我的名字叫haim 基本输出来自 c 中的代码,我不允许触摸.我必须实现eliminate_multiple_press和uneliminate_multiple_press,而不会介于两者之间的代码. 我到目前为止写的涡轮C代码是: #include #include #include volatile char key; volatile int i=0; void interrupt (*Int9save) (void); void interrupt
30 2024-04-07
编程技术问答社区
C语言中的字符串字头可以被修改吗?
我最近有一个问题,我知道一个指向以下代码中初始化的常数数组的指针,位于.rodata区域中,并且该区域仅可读. 但是,我在模式C11中看到,在此内存地址行为中的写作将不确定. 我知道Borland的Turbo-C编译器可以写在指针点的位置,这是因为处理器在当时的某些系统(例如MS-DOS)上以实际模式运行?还是它独立于处理器的操作模式?是否还有其他编译器将其写入指针,并且在受保护模式下使用处理器不会将任何内存漏洞发生? #include int main(void) { char *st = "aaa"; *st = 'b'; return 0; } 在此代码中用MS-DOS中的Turbo-C编译,您将能够写入内存 解决方案 是否还有其他编译器将写入指针的编译器,并且不会使用处理器以受保护的模式进行任何内存漏洞? GCC 3及以前用来支持gcc -fwriteable-strings 让您汇编旧的K&R C,显然
12 2024-04-07
编程技术问答社区
如何用C语言编写linux启动代码?
我是学习操作系统开发的新手.从我阅读的书中,它说启动加载程序将首先将MBR复制到0x7c00中,并以实际模式从那里开始. ,示例从16个位汇编代码开始. 但是,当我查看今天的Linux内核时,这似乎通过"不写组装"很有用. 但是,这是如何在Linux中专门完成的? 我可以粗略地想象可能有特殊的gcc选项和链接策略,但我看不到细节. 解决方案 我正在更多地阅读此问题,作为X-y问题.在我看来,问题更多是关于您是否可以在 c 中为自己的操作系统开发编写bootloader(引导代码).简单的答案是是,但不建议.现代Linux内核可能不是创建用 c 编写的引导加载程序的最佳信息来源,除非您了解其代码在做什么. 如果使用 gcc ,则对生成的代码有限制.在 gcc 的较新版本中,有一个-m16选项以这种方式记录: -m16 选项与-m32相同,只是它在组装输出开始时输出".code16gcc"汇编指令,以便二进制可以在16位以16位运行模式. 这有点欺骗性.尽管该
24 2024-04-06
编程技术问答社区
如何告诉GCC为真实模式生成16位代码
我正在编写实际模式功能,这应该是带有stackframes的正常函数,但是它应该使用%sp而不是%esp.有什么方法可以做吗? 解决方案 GCC 5.2.0(以及可能的早期版本)用-m16标志支持16位代码生成.但是,该代码几乎可以肯定会依靠32位处理器功能(例如32位宽寄存器),因此您应该仔细检查生成的组件. 来自man页面: -M16选项与-m32相同,除了它输出 " .code16gcc"汇编指令在组装输出的开头 因此二进制可以以16位模式运行. 其他解决方案 首先,GCC可以构建16位代码,因为Linux内核可以通过Realmode to ProtectMode,因此它甚至可以构建16位C代码. 然后,-M16选项由GCC> = 4.9支持,clang> = 3.5 GCC将忽略ASM(".code16"),您可以通过-s输出#APP #NO_APP 来看到它. Linux内核可以用Code16GCC.H(仅具有.code16gcc)
30 2024-04-06
编程技术问答社区
有没有一个针对8086的C语言编译器?
我有一个8086 CPU模拟器.它仅模拟8086个说明.我现在正在寻找一个C编译器来定位该模拟器.有没有C编译器可以做到这一点? 此外,拥有可用的libc等对我来说并不重要.模拟器使用自定义(IE,非PC)硬件,因此,任何LIBC甚至CTR0可能都必须重写 解决方案 bcc-布鲁斯的C编译器 来自 bcc(1) - Linux Man Page : 描述 bcc是一个简单的C编译器,生产8086汇编程序,此外,编译器编译时间选项允许80386或6809版本.编译器仅限于映射到其他整数类型之一的限制,理解传统的K&R C. 默认操作是从源文件中产生一个名为A.Out的8086可执行文件. 开放watcom 从编译器选项的描述/80x86运行时大会 0 (仅1个位)编译器将仅使用生成的对象代码中的8086个说明.这是 默认.最终的代码将在8086和所有向上兼容的处理器上运行.宏__SW_0 如果选择" 0",将被预定义 其他解决方案
22 2024-04-06
编程技术问答社区
什么是近、远和巨大的指针?
任何人都可以用一个合适的例子向我解释这些指示...当使用这些指针时? 解决方案 在过去的情况下,根据《涡轮C手册》,当您的整个代码和数据拟合到一个细分市场中时,几乎只有16位.一个遥远的指针由段和偏移组成,但没有进行归一化.并且一个巨大的指针自动归一化.可以想象,两个遥远的指针可以指向内存中的同一位置,但要不同,而指向同一内存位置的归一化巨型指针始终相等. 其他解决方案 主要示例是英特尔X86架构. 内部Intel 8086是一个16位处理器:其所有寄存器均为16位.但是,地址总线为20幅宽(1 MIB).这意味着您无法将整个地址保存在登记册中,将您限制在第一个64 KIB中. 英特尔的解决方案是创建16位"细分寄存器",其内容将被移动四个位并添加到地址中.例如: DS ("Data Segment") register: 1234 h DX ("D eXtended") register: + 5678h
12 2024-04-06
编程技术问答社区
汇编(emu8086)不允许将字节移动到8位寄存器中
我正在制作一个计算器类型程序,我用它从用户那里获取一个数字并存储它: mov ah, 01h int 21h mov offset num1, al ,在代码末尾,我将num1设置为 的字节 num1 db 0 给它一个默认值为0. 问题是,当我尝试将值从num1移回寄存器以执行实际操作时: mov bl, offset num1 我遇到了一个错误,说第二个操作数超过8位,我无法通过互联网/手册的任何搜索来弄清楚这一点. 另外,我使用偏移量,因为那是我最初教给他们的方式,我真的不理解它们. 解决方案 this: mov offset num1, al 应该是: mov num1, al 和: mov bl, offset num1 应该是: mov bl, num1 offset关键字应在您想要获得标签地址(或其在细分中的偏移量)的情况下使用.例如,如果您使用INT 21H / AH=09H打印字符串
16 2024-04-05
编程技术问答社区
如何用鼠标移动光标?
我正在开发X86组件中的Realmode操作系统.我设法使用键盘移动光标,但我想用鼠标移动光标.我不知道如何.我发现INT 33H与鼠标交易,但是我似乎无法使用INT 33H. 移动光标. 解决方案 中断int 10h to int 1Fh是BIOS中断.可以在启动操作系统之前使用它们. 中断int 20h to int 2Fh是DOS中断.只有在已经加载DOS时才能使用它们. 其他中断(例如int 33h)是设备驱动程序使用的中断. int 33h只能在加载DOS鼠标驱动程序时使用. 当没有安装鼠标驱动程序时要访问鼠标(例如,在您自己的启动加载程序中)时,您将直接访问硬件. 请参阅OSDEV中的以下文章: > https://wiki.osdev.org/ps/pps/2_mouse
18 2024-04-02
编程技术问答社区
为什么我的汇编子程序被调用了,尽管我没有在我的引导程序中的_start中调用它
我目前正在开发一个BIOS引导加载程序,而IM又有我的新汇总正在阅读它,我了解它的工作原理,但是有一些我不理解的事情涉及我的汇编代码的执行顺序. 基本上,即使我不打电话,我的子例子_印刷也是如何被调用的. 第二,即使在文件末尾,它也如何分配BIOS魔术号码,即使我没有到达. 我感谢任何帮助,谢谢. [ORG 0000:7C00] global _start _print: mov ah, 0x0e mov al, '[' int 0x10 mov al, '+' int 0x10 mov al, '[' int 0x10 ret _start: jmp $ times 510 - ($-$$) db 0 dw 0xAA55 解决方案 与操作系统运行的可执行文件不同,引导扇区没有办法指定任意入口点;它总是从第一个指令开始.因此,_start标签不能用作指定从哪里开始的方式.您必须从字
8 2024-04-02
编程技术问答社区
如何解决'bootloader.asm:30:错误。TIMES值-44为负值' NASM中的问题
我正在开发一个Hello World内核和Bootloader ...我写了此代码,但是当我尝试通过NASM进行编译时,它说:" bootloader.asm:30:error:times values -44是负面的"./p> bootloader.asm: [BITS 16] [ORG 0x7C00] MOV DL, 0x80 MOV DH, 0x0 MOV CH, 0x0 MOV CL, 0x02 MOV BX, 0x1000 MOV ES, BX MOV BX, 0x0 ReadFloppy: MOV AH, 0x02 MOV AL, 0x01 INT 0x13 JC ReadFloppy MOV AX, 0x1000 MOV DS, AX MOV ES, AX MOV FS, AX MOV GS, AX MOV SS, AX JMP 0x1000:0x0 TIMES 510 - ($ - $$) db 0 DW 0xAA55
16 2024-04-02
编程技术问答社区
为什么我不能让disk_read_error打印出来?
[org 0x7c00] ; declares the origin to 0x7c00 mov bp, 0x7c00 ; move the memory adress 0x7c00 to the base pointer, CS:IP always points to physical address 0x07C00. mov sp, bp ; move the base pointer to the stack pointer Hello_World: ; declares the label of the hello World position db 'Hello World!',0 ; declares the string Hello World! mov bx, Hello_World ; move
18 2024-04-02
编程技术问答社区
我无法在汇编中打印出一个字符
我正在尝试学习X86组件.我正在尝试制作玩具操作系统.我尝试打印出输入但失败的角色.输入中有问题吗?还是输出?我已经将AH设置为0x0e,并且使用了int 0x10,但它仍然不起作用.为什么不起作用? 注意:我是组装的新手,因此,如果我在文本或代码中遇到了问题,请不要说我有多愚蠢. char: db 0 mov ah, 0 int 0x16 mov ah, 0x0e mov al, [char] int 0x10 jmp $ times 510-($-$$) db 0 dw 0xaa55 解决方案 char: db 0 mov ah, 0 在汇编中,您需要将数据存储在执行代码的方式中.在此引导加载程序中,执行始于您放置数据项的顶部. CPU将尝试将其解释为指令,但会失败(大多数时候). 我尝试打印一个被输入的角色 收到字符作为输入后,您仍然需要将其实际存储在标记为 char 的内存中.如果您不这样做,那么指令mov al, [c
10 2024-04-02
编程技术问答社区
读取磁盘时出现奇怪的错误
所以,我一直在做一个爱好项目.创建我自己的操作系统.我开始了一段时间,但把它丢到了几天前.我只是修复了一项监督,该监督没有引起我想从我想阅读的领域阅读的任何内容.有了这个错误,一个新的错误就出现了,老实说,我甚至都不知道在哪里开始调试这个问题. 我正在编码主启动记录并使用GDB和QEMU调试,这是我的主启动记录的代码(使用Yasm组装) 对不起,如果我的代码不是很好.我不是汇编语言的专家... ; yasm boot.asm -fbin bits 16 %define part(n,l) section n vstart=l align=1 %define rpart(n,l) section n start=l align=1 ; ----------------------- ; part(entry, 0x7c00) ; ; --ENTRY---------------- ; _start: mov [boot_drive+0x7c00
38 2024-04-02
编程技术问答社区
汇编x86引导程序
因此,我找到了以下用于构建简单引导程序的教程:这是他的示例的开始,也是我难以理解的领域: start: mov ax, 07C0h ; Set up 4K stack space after this bootloader add ax, 288 ; (4096 + 512) / 16 bytes per paragraph mov ss, ax mov sp, 4096 mov ax, 07C0h ; Set data segment to where we're loaded mov ds, ax 我知道,迈克(Mike)正在尝试为他的启动加载器建造堆栈.该程序的开始时为内存中的07c0h.我不明白的是以下行'添加AX,288; (4096 + 512)/16字节每个段落'.他为什么要拿出堆栈和引导部门的总量,然后将其除以16位寄存器以开始堆栈段的开始?堆栈段不应该在启动器之后的20小
12 2024-04-02
编程技术问答社区
如何在bootloader中添加数字并将其显示在控制台?
我正在创建启动加载程序,该引导加载器应加上512到变量并打印结果,直到达到指定的数字为止.对我来说,这是4194304,但是问题是我真的不明白如何加上这些数字,因为最后我总是什么都没得到或损坏的字符串.那么我应该如何加上数字? cpu 386 bits 16 org 0h start: cld xor ax,ax mov ss,ax mov sp,7c00h ; setup stack mov ax,8000h mov es,ax ; initialize es w/ 8000h mov ds,ax ; initialize ds w/ 8000h ;=====================================================================================================
18 2024-04-02
编程技术问答社区
无中断显示文本
我正在尝试制作自己的引导加载程序.因为当我从16位更改为32位模式时,我将不会有任何中断,所以我将无法使用int 10h. 这是我到目前为止的代码: org 0x7c00 ; add to offsets xor ax, ax ; make it zero mov ds, ax ; ds=0 mov ss, ax ; stack starts at 0 cld mov ax, 0xb800 ; Ax = address of video memory mov es, ax xor di, di call print ; call thr print function hang: jmp hang ; constanly loop print: mov si, msg ; load msg into s
8 2024-04-02
编程技术问答社区