タイトルが示すように、DOSのタイマー割り込みの既存のハンドラーを自分のものに置き換えようとしています。さまざまなソリューションを幅広く検索した後、まさにそれを実行するアセンブリコードを見つけました。それをコンパイルしてテストすることもでき、それが機能することを確認しました。
ここでの問題は、私が見つけたコード(以下を参照)がTASM用に記述されていることです。これを、GCCでコンパイルする作成中のCコードで使用したいと思います。
コードをGAS(GNUアセンブラ)構文に変換しようとしましたが、機能しないようです(何度も試行したときに、ほとんどの場合、何らかのクラッシュが発生しました)。
誰かが私に解決策を教えてくれたらとてもありがたいです(GASがコンパイルできるアセンブリコードの動作バージョンであっても、Cですべてを実行する方法-"interrupt"キーワードは機能しません、また、「属性((割り込み))」なども、TASMとGCCの間を橋渡しする方法もありません。
また、私が使用しているDOSシステムは、実際にはFreeDOSがインストールされた仮想マシンを実行しているOracleVM VirtualBox Managerであり、Cに使用しているコンパイラはDJGPP開発環境で提供されるGCCです。 。
これは私が持っている動作中のTASMコードです(http://www.programmersheaven.com/mb/x86_asm/276128/276185/re-redefining-the-timer-interrupt-handler/から取得):
_stack SEGMENT STACK
db 32 DUP ('STACK ')
_stack ENDS
_code SEGMENT PARA 'CODE'
ASSUME CS:_code, SS:_stack
Lstart LABEL NEAR
JMP Linstall
;+---------------------------------------------
;| My New 1Ch INT
;| Print 'random' chars to the first video line
new_Int PROC FAR
DEC BYTE PTR CS:Counter
CLD
PUSH AX
MOV AX, 0B800h
MOV ES,AX ; ES = b800h
MOV DI,000h ; DI = 0000h
MOV AH,CS:Counter ; set foreground and background color
MOV AL,CS:Counter ; set char
MOV CX,80
REP STOSW ; From AX to ES:DI
POP AX
STI
IRET
new_Int ENDP
Counter DB 0Fh
;+-----------------------------------------
;| Store old INT and Install the new one
;|
Linstall LABEL NEAR
old_INT DD 00000000h
MOV AL,01Ch ;+-
MOV AH,35h ;| Save old_INT
INT 21h ;|
MOV WORD PTR [old_INT],BX
MOV WORD PTR [old_INT][2],ES
CLI ;+-
PUSH CS ;| Install
POP DS ;|
LEA DX,new_INT
MOV AL,1Ch
MOV AH,25h
INT 21h
MOV AH,0 ;+-
INT 16H ;| Wait for a keypress
;+-----------------------------------------
;| Disinstall and exit
CLI
PUSH DS
LDS DX,CS:[old_INT] ;+-
MOV AL,1Ch ;| Disinstall int
MOV AH,25h ;|
INT 21h ;|
POP DS
STI
MOV AL,0 ;+-
MOV AH,4Ch ;| Exit
INT 21h ;|
_code ENDS
END Lstart
それは私のマシンで完全に動作します。プログラムを起動すると、コンソールの最初の行全体が、常に変化するカラフルな文字に置き換えられているのがわかります。
そして、これは上記のコードをGAS構文に変換する私の試みです。
.file "ttv2.s"
# Define a variable for "randomizing" characters and colors
.globl _MyVar
.section .bss
_MyVar:
.space 1
.section .text
# Define a variable for storing the address of the current ISR
.globl _OldInt
.section .bss
.p2align 2
_OldInt:
.space 4
.section .text
# Program entry point
.text
.globl start
start:
jmp _Install
# This is the new Interrupt Service Routine that is going to be installed
.globl _NewInt
_NewInt:
movb _MyVar, %al
decb %al # Decrement our variable
movb %al, _MyVar
cld
pushw %ax
movw $0xB800, %ax
movw %ax, %es # ES = 0xB800
movw $0, %di # DI = 0
movb _MyVar, %ah # Set the foreground and background colors
movb _MyVar, %al # Set the charater to be displayed
movw $80, %cx # The screen is 80 characters wide
rep stosw # Start copying from AX to AS:DI
popw %ax
sti
iret
.globl _Install
_Install:
# Save old ISR address
movb $0x1C, %al # Set the code for the Timer interrupt
movb $0x35, %ah # 0x35 is the code for getting the current ISR
int $0x21 # 0x21 is the interrupt fot s/getting ISRs
movw %es, %dx #
shll $16, %edx # Save the address of the
movw %bx, %dx # old interrupt handler
movl %edx, _OldInt #
# Install the new ISR
cli
pushw %cs
popw %ds
lea _NewInt, %dx # Set the address of the ISR we're installing
movb $0x1C, %al # Set the code for the Timer interrupt
movb $0x25, %ah # 0x25 is the code for setting a new ISR
int $0x21 # 0x21 is the interrupt fot s/getting ISRs
# Wait for a key press
movl $0, %eax
int $0x16
.globl _Uninstall
_Uninstall:
cli
pushw %ds
lds %cs:_OldInt, %dx # Install the address of the old ISR
movb $0x1C, %al # Set the code for the Timer interrupt
movb $0x25, %ah # 0x25 is the code for setting a new ISR
int $0x21 # 0x21 is the interrupt fot s/getting ISRs
popw %ds
sti
.globl _End
_End:
# Exit
movb $0, %al
movb $0x4C, %ah # 0x4C is the code for program exit in DOS
int $0x21
.ident "GCC: (GNU) 4.5.2"
次のコマンドを使用してファイル(「ttv2.s」と呼ばれる)をコンパイルします。
as -o ttv2.o ttv2.s
ld -o ttv2.exe ttv2.o
結果のEXEファイルを実行すると(アセンブリおよびリンケージ中に警告やエラーは発生しません)、プログラムは「リング0の例外0D(および多数のレジスタ値)」というエラーでクラッシュします。ただし、TASMバージョンは問題なく動作します。したがって、コードを変換する方法、または最終的なEXEを作成する方法のいずれかに問題があると推測しています。または両方。
少しの追加情報、それが何らかの形で役立つ場合:
- インストールコマンド( )を削除
int $0x21
してもクラッシュは発生せず、プログラムはキーを押すのを待ってから終了します。 - インストールコマンドを保持しているが、キー待機コマンド( )を削除する
int $0x16
と、プログラムはすぐに終了し、クラッシュは発生しません。 - インストールコマンドを保持し、wait-for-keyコマンドをアクティブな遅延ループ(40億回の反復の単純なループ)に置き換えると、wait-for-keyコマンドが配置されたときと同じようにプログラムがクラッシュします。 、しかし、すぐにではなく、数秒後。
- どちらの場合も(キーを押すか遅延して)クラッシュすると、2つのインストールコマンドの1つだけを削除しても、プログラムがクラッシュします。
あらゆる支援を事前に感謝し、長い投稿をお詫びします...