我正在研究x86和实时系统,我有一个问题,那就是:
x86遵循哪些步骤来处理任何中断?
我在今年1月份将x86程序集作为业余爱好,因此我可以制作适用于旧PC 80和Tandy 1000等老式8086计算机的游戏,但我找到的书并没有完全讲授这个特定主题.虽然有些dos和bios中断了这项工作,但它们远非完美.
我的主要问题是在不停止程序的情况下读取按键的键盘状态.我发现了一些方法,但它们非常有限.INT 21h,AH 0Ch读取最后按下的键,但采用文本编辑方式.它不仅一次只能读取一个键,而且类似记事本的命中检测使得无法知道密钥被保持了多长时间.在Google旅行期间,我也看到了60h到64h端口的引用,但就是这样,引用.实际解释和工作代码几乎不存在.或者也许我只是在使用搜索引擎时那么糟糕.
我需要知道的是密钥是否被按下.最好的解决方案是拥有所有键盘键的缓冲区/数组并读取其状态; 1表示它已经下降,0表示它不是.或者只是访问已被命中和释放的最后一个键的列表将是很好的(当然,有一种方法可以清除缓冲区).谁能指出我正确的方向?
编辑:首先,我应该提到我使用Borland TASM.现在我编写了你的代码并且它很有效,尽管我几乎不愿意承认我不理解它的一半.我试图让它与TASM兼容,但它只是在屏幕上创建垃圾并冻结.
这就是我想出来的;
.MODEL TINY
.STACK 256
.DATA
kbdbuf DB 128 DUP (0)
msg1 db "Press and hold ESC", 13, 10, "$"
msg2 db "ESC pressed, release ESC", 13, 10, "$"
msg3 db "ESC released", 13, 10, "$"
.CODE
main PROC
org 0100h
mov ax, @data
mov ds, ax
xor ax, ax
mov es, ax
cli ; update ISR address w/ ints disabled
push word [es:9*4+2] ; preserve ISR address
push …Run Code Online (Sandbox Code Playgroud) 我读到该MOV指令不能为其两个操作数都有内存位置.
喜欢:MOV [0012H], [0016H]不允许.
为什么这样?
其他指令可以为其两个操作数设置内存位置吗?
这是一些C,在我正在学习的教科书中找到:
...
do {
...
n--;
} while (n > 0)
...
Run Code Online (Sandbox Code Playgroud)
我假设n是在%edx.
生成的汇编代码是:
testl %edx, %edx
jle .L5
Run Code Online (Sandbox Code Playgroud)
我明白jle测试小于或等于(SF ^ OF) | ZF.但是我不确定这条指令是如何对应的n > 0.有谁能解释一下?
首先,我是8086大会的新手,我很难掌握这些知识.不过,我会尽我所能.
我一直在尝试编写代码来生成0-9范围内的随机数.在研究了几个例子和建议之后,这就是我最终的结果.我没有对检索到的时钟计数应用任何数学函数,为简单起见而且我认为这是不必要的.由于某些原因,我最终得到了一些数字,比如1,3和9这样的数字少了6,7倍.我相信这是因为我采用了时钟滴答的较低阶,其中值改变了迅速.
我的目的是模拟骰子卷,后来将下面代码的范围改为1-6.我的问题是,这足以达到我的目的吗?或者有更好的方法吗?
代码:
RANDGEN: ; generate a rand no using the system time
RANDSTART:
MOV AH, 00h ; interrupts to get system time
INT 1AH ; CX:DX now hold number of clock ticks since midnight
; lets just take the lower bits of DL for a start..
MOV BH, 57 ; set limit to 57 (ASCII for 9)
MOV AH, DL
CMP AH, BH ; compare with value in DL,
JA RANDSTART ; if more, regenerate. if not, continue... …Run Code Online (Sandbox Code Playgroud) 我正在尝试在程序集中创建一个子程序,它将在屏幕上绘制一个正方形.我不认为我可以像在C++中那样将参数传递给子程序,所以我想我可以使用堆栈来存储和访问参数(我不能使用公共数据寄存器,因为有太多变量到通过).
问题是(我记得在某处阅读)当我使用call命令到当前"程序"的地址时,它被保存在堆栈中,因此当它使用"ret"命令时它将知道返回的位置.但是,如果我存储在堆栈上的东西,然后调用函数,我必须保存在某个地方的地址(也就是在堆栈的顶部),然后安全地弹出的参数.然后在代码完成之后并且在调用"ret"之前,我将不得不推回地址.
我对吗?并且,如果是,我在哪里可以存储地址(我不认为地址只有1个字节长,因此它适合AX或BX或任何其他数据寄存器).我可以使用IP来执行此操作(虽然我知道这用于其他事情)?
这就是我的想象:
[BITS 16]
....
main:
mov ax,100b
push ax
call rectangle ;??--pushes on the stack the current address?
jml $
rectangle:
pop ax ;??--this is the addres of main right(where the call was made)?
pop bx ;??--this is the real 100b, right?
....
push ax
ret ;-uses the address saved in stack
Run Code Online (Sandbox Code Playgroud) 在我的8086汇编程序中执行循环时,有一个键盘按键阈值,如果你按键太多次,PC扬声器将开始发出哔哔声.这是令人讨厌的,它减慢了我的程序爬行速度,因为CPU必须跳离我的程序并花半秒钟来驱动扬声器.
几个月前我开始在实际硬件上测试我的程序之前,我甚至都不知道这个问题.这个问题在DosBox中不是问题,甚至在DosBox中安装的Dos 6.22中也不是问题.所以它必须是PC BIOS内置的一些低级硬件中断,我不太了解这些东西.
它出现在我的286机器和我的Pentium mmx笔记本电脑上,无论操作系统如何.
即使它只是一个死循环,我甚至没有轮询键盘输入,如果我按太多键也会发出蜂鸣声
我已经尝试将我的输入代码包装在cli和sti中,希望能够从系统中屏蔽我的键盘输入,但这确实不起作用.我只在程序中的一个奇点处收集扫描码,所以其余的时间都启用了中断.所以绝大多数时候仍然会发出哔哔声.
必须有一些我可以禁用的硬件寄存器或其他东西.我仔细查看了Boch的端口列表(http://bochs.sourceforge.net/techspec/PORTS.LST),寻找类似的东西,但没有看到任何东西.
也许我可以关闭中断?我想很多汇编程序员一定遇到过这个问题,但Google在这里根本没有帮助我.
我有一个小的8086模拟器,我有一个长期的错误2年,现在AF在子内部表现不正常并添加说明.
我目前计算其值的方法是8位数和减法:
uint8_t base=... , subt=...
base=base&0xF;
subt=subt&0xF; //isolate bottom nibble
if((int16_t)base-subt>7 || (int16_t)base-subt<-7){
flags.af=1;
}else{
flags.af=0;
}
Run Code Online (Sandbox Code Playgroud)
(假设有一个指令sub base,subt)
并添加它是这样的:
uint8_t base=... , adder=...
base=base&0xF;
adder=adder&0xF; //isolate bottom nibble
if(base+adder>7 || base+adder<-7){
flags.af=1;
}else{
flags.af=0;
}
Run Code Online (Sandbox Code Playgroud)
(对于像这样的指令add base,adder)
如何正确计算模拟器中的AF标志以获取此类指令?
我想在汇编中打印0到9的多个数字表.所以我编写下面的代码:
data_seg segment
I DB 0D
J DB 0D
R DB ?
DIVER DB 10D
data_seg ends
stack_seg segment
stack_seg ends
code_seg segment
MAIN proc far
assume cs:code_seg, ds:data_seg, ss:stack_seg
MOV AX,data_seg
MOV DS,AX
FOR1:
MOV J,0D
FOR2:
MOV AX,0H
MOV AL,I
MUL J
DIV DIVER
MOV R,AH
ADD AL,48D
MOV AH,0EH
INT 10H
MOV AL,R
ADD AX,48D
MOV AH,0EH
INT 10H
MOV AX,32D
MOV AH,0EH
INT 10H
INC J
MOV AX,0
MOV AL,J
SUB AX,10D
JNZ FOR2
INC I …Run Code Online (Sandbox Code Playgroud) 我在8086处理器的汇编中编写了一个游戏,并在名为DOSBox的DOS模拟器上运行它.
现在我想向其他人展示游戏而不必下载模拟器.基本上,我想将8086程序集编译为现代操作系统的可执行文件.这可能,还是应该将其转换为另一种汇编语言?如果是这样,有没有办法自动进行此转换?