我无法让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) 在我的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大会的初学者.我正在学习我在旧货店里发现的一本90年代早期的旧书.我认为像1992年那样编程可能会很有趣.
无论如何,我已经完成了这本书,现在我已经在我的旧Win95笔记本电脑上的命令提示符下编写了一些程序.
切换到使用'les'指令后,我遇到了这个问题没有按预期工作的问题.但是,当我手动设置适当地址的ES和DI寄存器时,它确实有效.
;************************************
; STACK SEGMENT
;************************************
TheStack SEGMENT STACK ;STACK specifies the stack segment
db 64 dup (THESTACK) ;reserves 512 bytes for the stack
TheStack ENDS
;************************************
; END STACK SEGMENT
;************************************
;************************************
; DATA SEGMENT
;************************************
Data SEGMENT
BufAddr DD 0b8000000h
Data ENDS
;************************************
; END DATA SEGMENT
;************************************
;************************************
; CODE SEGMENT
;************************************
Code SEGMENT
assume CS:Code,DS:Data
MAIN PROC
Start: ;execution begins
;setup input for stosw
les di, DWORD PTR BufAddr
mov cx,0f4fh ;cx contains the …Run Code Online (Sandbox Code Playgroud) 在DOSBox 0.74中,当我尝试使用int 21h的函数3ch打开任何文件上的文件句柄时,文件的数据被清除,永久减少到0字节大小.
我测试过的文件都位于Windows 10的文档目录中,该目录在DOSBox中作为驱动器E安装.
这是导致问题的代码.它应该打开,然后关闭文件句柄.CF永远不会设置,所以没有错误代码.AX中的文件句柄设置为5.
mov ax, varData
mov ds, ax ;Load the variable segment into ds
;word variable handle is defined here
;string fname is defined here
mov ah, 3ch ;select open file handle function
lea dx, fname ;dx points to file's name ("TESTFILE")
mov cl, 1 ;read only
int 21h ;open the file handle
mov handle, ax ;copy handle into variable
mov ah, 3eh ;close handle function
mov bx, handle ;closing previously opened file handle
int 21h …Run Code Online (Sandbox Code Playgroud) 我正在开发一款使用视频模式 13h 的 DOS 游戏。
我一直遇到屏幕撕裂的问题,但直到今天我一直忽略这个问题。我认为修复这将是一个挑战,因为它将涉及延迟像素写入一段精确的时间。但这实际上是一个非常简单的修复。
您所要做的就是等待重新设置 VGA 状态字节的垂直回扫位(位 3),该位在彩色模式下可在端口 0x3da 上使用。
所以我只需要修改这个旧程序,它将我的帧缓冲区写入从 A000:0000 开始的 VGA 像素缓冲区:
WRITE_FRAME PROC
;WRITES ALL 64,000 PIXELS (32,000 WORDS) IN THE FRAME BUFFER TO VIDEO MEMORY
push es
push di
push ds
push si
push cx
mov cx, frame
mov ds, cx
xor si, si ;ds:si -> frame buffer (source)
mov cx, vidMemSeg
mov es, cx
xor di, di ;es:di -> video memory (destination)
mov cx, (scrArea)/2 ;writing 32,000 words of pixels
rep movsw …Run Code Online (Sandbox Code Playgroud) 我注意到我正在编写的一些代码中存在潜在的错误。
我认为,如果我使用mov ax, seg segment_name,该程序可能是不可移植的,并且只能在特定配置的一台机器上运行,因为加载位置可能因机器而异。
所以我决定在两台运行 DOS 的不同机器上反汇编一个只包含一条指令的程序,我发现问题神奇地解决了。
一号机上的调试输出:0C7A:014C B8BB0C MOV AX,0CBB
二号机器上的调试输出:06CA:014C B80B07 MOV AX,070B
十六进制转储程序后,我发现未更改的字节实际上是B84200.
手动将这些字节插入到程序中会导致mov ax, 0042
那么 PE 格式是否存储对这些指令的引用并在运行时更新它们?
dos relocation portable-executable memory-segmentation x86-16
在保护模式下调用内存地址低于当前函数的函数时,我遇到异常。异常会因代码配置而异,有时是一般保护错误,有时是无效的操作码等。
这是一个程序的源代码,该程序在硬件上产生一般保护故障,并在 DOSBox 中产生双重故障。相关代码在段中seg32。故障发生在func1,当它尝试回拨func2
single segment stack
assume cs:single,ds:single,ss:single
gdesc struc ;global descriptor structure definition
limit_lo dw 0ffffh ;low word of 20-bit limit (bits 15:0)
base_lo dw ? ;low word of base address (bits 15:0)
base_mid db ? ;middle byte of base address (bits 23:16)
priv db ? ;privilege and type bits
limit_hi db ? ;granularity, operand size, hi nybble of limit (bits 19:16)
base_hi db ? ;high byte of base address (bits 31:24)
gdesc …Run Code Online (Sandbox Code Playgroud) 为什么此代码片段中指针周围的括号是必要的?
cout << (*pStr).size() << endl;
Run Code Online (Sandbox Code Playgroud)
回顾我的书后,我终于在我看过的脚注中发现了一点小小的提及。
它说:“——这确保了点运算符将应用于指针指向的对象。”
为什么这不起作用?
cout << *pName.size() << endl;
Run Code Online (Sandbox Code Playgroud)
我之所以这么问,是因为我的书没有给出很好的解释,而且我只是浪费了很多时间试图找出为什么这行代码给我带来了错误。(当然我忘了括号)