Added a new debugging channel io to allow read/writes on a port to be
logged to a file.
This commit is contained in:
parent
b745eaa466
commit
bdc48bd1e4
|
@ -0,0 +1,223 @@
|
|||
cat > /dev/null <<EOF
|
||||
The above line is necessary, leave it alone!!
|
||||
--------------------------------------------------------------------
|
||||
|
||||
DOING A HARDWARE TRACE IN WINE
|
||||
------------------------------
|
||||
|
||||
The primary reason to do this is to reverse engineer a hardware device
|
||||
for which you don't have documentation, but can get to work under Wine.
|
||||
|
||||
This lot is aimed at parallel port devices, and in particular parallel port
|
||||
scanners which are now so cheap they are virtually being given away. The
|
||||
problem is that few manufactures will release any programming information which
|
||||
prevents drivers being written for Sane, and the traditional technique of using
|
||||
DOSemu to produce the traces does not work as the scanners invariably only have
|
||||
drivers for Windows.
|
||||
|
||||
Please note that I have not been able to get my scanner working properly (a
|
||||
UMAX Astra 600P), but a couple of people have reported success with at least
|
||||
the Artec AS6e scanner. I am not in the process of developing any driver nor do
|
||||
I intend to, so don't bug me about it. My time is now spent writting programs
|
||||
to set things like battery save options under Linux on Toshiba laptops, ans as
|
||||
such I don't have any spare time for writting a driver for a parallel port
|
||||
scanner etc.
|
||||
|
||||
Presuming that you have compiled and installed wine the first thing to do is is
|
||||
to enable direct hardware access to your parallel port. To do this edit
|
||||
wine.conf (usually in /usr/local/etc) and in the ports section add the
|
||||
following two lines
|
||||
|
||||
read=0x378,0x379,0x37a,0x37c,0x77a
|
||||
write=0x378,x379,0x37a,0x37c,0x77a
|
||||
|
||||
This adds the necessary access required for SPP/PS2/EPP/ECP parallel port on
|
||||
LPT1. You will need to adjust these number accordingly if your parallel port is
|
||||
on LPT2 or LPT0.
|
||||
|
||||
When starting wine use the following command line, where XXXX is the program
|
||||
you need to run in order to access your scanner, and YYYY is the file your
|
||||
trace will be stored in:
|
||||
|
||||
wine -debugmsg +io XXXX 2> >(sed 's/^[^:]*:io:[^ ]* //' > YYYY)
|
||||
|
||||
You will need large amounts of hard disk space (read hundreds of megabytes if
|
||||
you do a full page scan), and for reasonable performance a really fast
|
||||
processor and lots of RAM.
|
||||
|
||||
You might well find the log compression program that David Campbell
|
||||
<campbell@torque.net> wrote helpfull in reducing the size of the log files.
|
||||
This can be obtained by the following command:
|
||||
|
||||
sh ioport-trace-hints
|
||||
|
||||
This should extract shrink.c (which is located at the end of this file. Compile
|
||||
the log compression program by:
|
||||
|
||||
cc shrink.c -o shrink
|
||||
|
||||
Use the shrink program to reduce the physical size of the raw log as follows:
|
||||
|
||||
cat log | shrink > log2
|
||||
|
||||
The trace has the basic form of
|
||||
|
||||
XXXX > YY @ ZZZZ:ZZZZ
|
||||
|
||||
where XXXX is the port in hexidecimal being accessed, YY is the data written
|
||||
(or read) from the port, and ZZZZ:ZZZZ is the address in memory of the
|
||||
instruction that accessed the port. The direction of the arrow indicates
|
||||
whether the data was written or read from the port.
|
||||
|
||||
> data was written to the port
|
||||
< data was read from the port
|
||||
|
||||
|
||||
My basic tip for interperating these logs is to pay close attention to the
|
||||
addresses of the IO instructions. There grouping and sometimes proximity should
|
||||
reveal the presence of subroutines in the driver. By studying the different
|
||||
versions you should be able to work them out. For example consider the
|
||||
following section of trace from my UMAX Astra 600P
|
||||
|
||||
0x378 > 55 @ 0297:01ec
|
||||
0x37a > 05 @ 0297:01f5
|
||||
0x379 < 8f @ 0297:01fa
|
||||
0x37a > 04 @ 0297:0211
|
||||
0x378 > aa @ 0297:01ec
|
||||
0x37a > 05 @ 0297:01f5
|
||||
0x379 < 8f @ 0297:01fa
|
||||
0x37a > 04 @ 0297:0211
|
||||
0x378 > 00 @ 0297:01ec
|
||||
0x37a > 05 @ 0297:01f5
|
||||
0x379 < 8f @ 0297:01fa
|
||||
0x37a > 04 @ 0297:0211
|
||||
0x378 > 00 @ 0297:01ec
|
||||
0x37a > 05 @ 0297:01f5
|
||||
0x379 < 8f @ 0297:01fa
|
||||
0x37a > 04 @ 0297:0211
|
||||
0x378 > 00 @ 0297:01ec
|
||||
0x37a > 05 @ 0297:01f5
|
||||
0x379 < 8f @ 0297:01fa
|
||||
0x37a > 04 @ 0297:0211
|
||||
0x378 > 00 @ 0297:01ec
|
||||
0x37a > 05 @ 0297:01f5
|
||||
0x379 < 8f @ 0297:01fa
|
||||
0x37a > 04 @ 0297:0211
|
||||
|
||||
As you can see their is a repeating structure starting at address 0297:01ec
|
||||
that consists of four io access on the parallel port. Looking at it the first
|
||||
io access writes a changing byte to the data port the second always writes the
|
||||
byte 0x05 to the control port, then a value which always seems to 0x8f is read
|
||||
from the status port at which point a byte 0x04 is written to the control port.
|
||||
By studying this and other sections of the trace we can write a C routine that
|
||||
emulates this, shown below with some macros to make reading/writing on the
|
||||
parallel port easier to read.
|
||||
|
||||
|
||||
#define r_dtr(x) inb(x)
|
||||
#define r_str(x) inb(x+1)
|
||||
#define r_ctr(x) inb(x+2)
|
||||
#define w_dtr(x,y) outb(y, x)
|
||||
#define w_str(x,y) outb(y, x+1)
|
||||
#define w_ctr(x,y) outb(y, x+2)
|
||||
|
||||
/*
|
||||
* Seems to be sending a command byte to the scanner
|
||||
*
|
||||
*/
|
||||
int udpp_put(int udpp_base, unsigned char command)
|
||||
{
|
||||
int loop,value;
|
||||
|
||||
w_dtr(udpp_base, command);
|
||||
w_ctr(udpp_base, 0x05);
|
||||
|
||||
for (loop=0;loop<10;loop++)
|
||||
if (((value=r_str(udpp_base)) & 0x80)!=0x00) {
|
||||
w_ctr(udpp_base, 0x04);
|
||||
return value & 0xf8;
|
||||
}
|
||||
|
||||
return (value & 0xf8) | 0x01;
|
||||
}
|
||||
|
||||
|
||||
For the UMAX Astra 600P only seven such routines exist (well 14 really, seven
|
||||
for SPP and seven for EPP). Whether you choose to disassemble the driver at
|
||||
this point to verify the routines is your own choice. If you do, the address
|
||||
from the trace should help in locating them in the disassembly.
|
||||
|
||||
You will probably then find it useful to write a script/perl/C program to
|
||||
analyse the logfile and decode them futher as this can reveal higher level
|
||||
grouping of the low level routines. For example from the logs from my UMAX
|
||||
Astra 600P when decoded futher reveal (this is a small snippet)
|
||||
|
||||
|
||||
start:
|
||||
put: 55 8f
|
||||
put: aa 8f
|
||||
put: 00 8f
|
||||
put: 00 8f
|
||||
put: 00 8f
|
||||
put: c2 8f
|
||||
wait: ff
|
||||
get: af,87
|
||||
wait: ff
|
||||
get: af,87
|
||||
end: cc
|
||||
start:
|
||||
put: 55 8f
|
||||
put: aa 8f
|
||||
put: 00 8f
|
||||
put: 03 8f
|
||||
put: 05 8f
|
||||
put: 84 8f
|
||||
wait: ff
|
||||
|
||||
From this it is easy to see that put routine is oftern gouped together in five
|
||||
sucessive calls sending information to the scanner. Once these are understood
|
||||
it should be possible to process the logs further to show the higher level
|
||||
routines in an easy to see format. Once the higest level format that you
|
||||
can derive from this process is understood, you then need to produce a
|
||||
series of scans varying only one parameter between them, so you can
|
||||
discover how to set the various parameters for the scanner.
|
||||
|
||||
|
||||
Jonathan Buzzard
|
||||
<jab@hex.prestel.co.uk>
|
||||
|
||||
|
||||
--------------------------------------------------------------------
|
||||
The following is the shrink.c program.
|
||||
EOF
|
||||
cat > shrink.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void
|
||||
main (void)
|
||||
{
|
||||
char buff[256], lastline[256];
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
lastline[0] = 0;
|
||||
|
||||
while (!feof (stdin))
|
||||
{
|
||||
fgets (buff, sizeof (buff), stdin);
|
||||
if (strcmp (buff, lastline) == 0)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count > 1)
|
||||
fprintf (stdout, "# Last line repeated %i times #\n", count);
|
||||
fprintf (stdout, "%s", buff);
|
||||
strcpy (lastline, buff);
|
||||
count = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
169
include/debug.h
169
include/debug.h
|
@ -68,90 +68,91 @@
|
|||
#define dbch_int19 60
|
||||
#define dbch_int21 61
|
||||
#define dbch_int31 62
|
||||
#define dbch_ipaddress 63
|
||||
#define dbch_key 64
|
||||
#define dbch_keyboard 65
|
||||
#define dbch_ldt 66
|
||||
#define dbch_listbox 67
|
||||
#define dbch_listview 68
|
||||
#define dbch_local 69
|
||||
#define dbch_mci 70
|
||||
#define dbch_mcianim 71
|
||||
#define dbch_mciwave 72
|
||||
#define dbch_mdi 73
|
||||
#define dbch_menu 74
|
||||
#define dbch_message 75
|
||||
#define dbch_metafile 76
|
||||
#define dbch_midi 77
|
||||
#define dbch_mmaux 78
|
||||
#define dbch_mmio 79
|
||||
#define dbch_mmsys 80
|
||||
#define dbch_mmtime 81
|
||||
#define dbch_module 82
|
||||
#define dbch_mpr 83
|
||||
#define dbch_msacm 84
|
||||
#define dbch_msg 85
|
||||
#define dbch_nativefont 86
|
||||
#define dbch_nonclient 87
|
||||
#define dbch_ntdll 88
|
||||
#define dbch_ole 89
|
||||
#define dbch_pager 90
|
||||
#define dbch_palette 91
|
||||
#define dbch_pidl 92
|
||||
#define dbch_print 93
|
||||
#define dbch_process 94
|
||||
#define dbch_profile 95
|
||||
#define dbch_progress 96
|
||||
#define dbch_prop 97
|
||||
#define dbch_psapi 98
|
||||
#define dbch_psdrv 99
|
||||
#define dbch_rebar 100
|
||||
#define dbch_reg 101
|
||||
#define dbch_region 102
|
||||
#define dbch_relay 103
|
||||
#define dbch_resource 104
|
||||
#define dbch_s 105
|
||||
#define dbch_scroll 106
|
||||
#define dbch_security 107
|
||||
#define dbch_segment 108
|
||||
#define dbch_selector 109
|
||||
#define dbch_sem 110
|
||||
#define dbch_sendmsg 111
|
||||
#define dbch_shell 112
|
||||
#define dbch_shm 113
|
||||
#define dbch_snoop 114
|
||||
#define dbch_sound 115
|
||||
#define dbch_static 116
|
||||
#define dbch_statusbar 117
|
||||
#define dbch_stress 118
|
||||
#define dbch_string 119
|
||||
#define dbch_syscolor 120
|
||||
#define dbch_system 121
|
||||
#define dbch_tab 122
|
||||
#define dbch_task 123
|
||||
#define dbch_text 124
|
||||
#define dbch_thread 125
|
||||
#define dbch_thunk 126
|
||||
#define dbch_timer 127
|
||||
#define dbch_toolbar 128
|
||||
#define dbch_toolhelp 129
|
||||
#define dbch_tooltips 130
|
||||
#define dbch_trackbar 131
|
||||
#define dbch_treeview 132
|
||||
#define dbch_tweak 133
|
||||
#define dbch_uitools 134
|
||||
#define dbch_updown 135
|
||||
#define dbch_ver 136
|
||||
#define dbch_virtual 137
|
||||
#define dbch_vxd 138
|
||||
#define dbch_win 139
|
||||
#define dbch_win16drv 140
|
||||
#define dbch_win32 141
|
||||
#define dbch_wing 142
|
||||
#define dbch_winsock 143
|
||||
#define dbch_wnet 144
|
||||
#define dbch_x11 145
|
||||
#define dbch_x11drv 146
|
||||
#define dbch_io 63
|
||||
#define dbch_ipaddress 64
|
||||
#define dbch_key 65
|
||||
#define dbch_keyboard 66
|
||||
#define dbch_ldt 67
|
||||
#define dbch_listbox 68
|
||||
#define dbch_listview 69
|
||||
#define dbch_local 70
|
||||
#define dbch_mci 71
|
||||
#define dbch_mcianim 72
|
||||
#define dbch_mciwave 73
|
||||
#define dbch_mdi 74
|
||||
#define dbch_menu 75
|
||||
#define dbch_message 76
|
||||
#define dbch_metafile 77
|
||||
#define dbch_midi 78
|
||||
#define dbch_mmaux 79
|
||||
#define dbch_mmio 80
|
||||
#define dbch_mmsys 81
|
||||
#define dbch_mmtime 82
|
||||
#define dbch_module 83
|
||||
#define dbch_mpr 84
|
||||
#define dbch_msacm 85
|
||||
#define dbch_msg 86
|
||||
#define dbch_nativefont 87
|
||||
#define dbch_nonclient 88
|
||||
#define dbch_ntdll 89
|
||||
#define dbch_ole 90
|
||||
#define dbch_pager 91
|
||||
#define dbch_palette 92
|
||||
#define dbch_pidl 93
|
||||
#define dbch_print 94
|
||||
#define dbch_process 95
|
||||
#define dbch_profile 96
|
||||
#define dbch_progress 97
|
||||
#define dbch_prop 98
|
||||
#define dbch_psapi 99
|
||||
#define dbch_psdrv 100
|
||||
#define dbch_rebar 101
|
||||
#define dbch_reg 102
|
||||
#define dbch_region 103
|
||||
#define dbch_relay 104
|
||||
#define dbch_resource 105
|
||||
#define dbch_s 106
|
||||
#define dbch_scroll 107
|
||||
#define dbch_security 108
|
||||
#define dbch_segment 109
|
||||
#define dbch_selector 110
|
||||
#define dbch_sem 111
|
||||
#define dbch_sendmsg 112
|
||||
#define dbch_shell 113
|
||||
#define dbch_shm 114
|
||||
#define dbch_snoop 115
|
||||
#define dbch_sound 116
|
||||
#define dbch_static 117
|
||||
#define dbch_statusbar 118
|
||||
#define dbch_stress 119
|
||||
#define dbch_string 120
|
||||
#define dbch_syscolor 121
|
||||
#define dbch_system 122
|
||||
#define dbch_tab 123
|
||||
#define dbch_task 124
|
||||
#define dbch_text 125
|
||||
#define dbch_thread 126
|
||||
#define dbch_thunk 127
|
||||
#define dbch_timer 128
|
||||
#define dbch_toolbar 129
|
||||
#define dbch_toolhelp 130
|
||||
#define dbch_tooltips 131
|
||||
#define dbch_trackbar 132
|
||||
#define dbch_treeview 133
|
||||
#define dbch_tweak 134
|
||||
#define dbch_uitools 135
|
||||
#define dbch_updown 136
|
||||
#define dbch_ver 137
|
||||
#define dbch_virtual 138
|
||||
#define dbch_vxd 139
|
||||
#define dbch_win 140
|
||||
#define dbch_win16drv 141
|
||||
#define dbch_win32 142
|
||||
#define dbch_wing 143
|
||||
#define dbch_winsock 144
|
||||
#define dbch_wnet 145
|
||||
#define dbch_x11 146
|
||||
#define dbch_x11drv 147
|
||||
/* Definitions for classes identifiers */
|
||||
#define dbcl_fixme 0
|
||||
#define dbcl_err 1
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "debugtools.h"
|
||||
#endif
|
||||
|
||||
#define DEBUG_CHANNEL_COUNT 147
|
||||
#define DEBUG_CHANNEL_COUNT 148
|
||||
#ifdef DEBUG_RUNTIME
|
||||
short debug_msg_enabled[][DEBUG_CLASS_COUNT] = {
|
||||
{1, 1, 0, 0},
|
||||
|
@ -154,6 +154,7 @@ short debug_msg_enabled[][DEBUG_CLASS_COUNT] = {
|
|||
{1, 1, 0, 0},
|
||||
{1, 1, 0, 0},
|
||||
{1, 1, 0, 0},
|
||||
{1, 1, 0, 0},
|
||||
};
|
||||
const char* debug_ch_name[] = {
|
||||
"1",
|
||||
|
@ -219,6 +220,7 @@ const char* debug_ch_name[] = {
|
|||
"int19",
|
||||
"int21",
|
||||
"int31",
|
||||
"io",
|
||||
"ipaddress",
|
||||
"key",
|
||||
"keyboard",
|
||||
|
|
|
@ -489,21 +489,41 @@ BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context )
|
|||
{
|
||||
case 0x6c:
|
||||
*((BYTE *)data) = IO_inport( DX_sig(context), 1);
|
||||
TRACE(io, "0x%x < %02x @ %04x:%04x\n", DX_sig(context),
|
||||
*((BYTE *)data), CS_sig(context), IP_sig(context));
|
||||
break;
|
||||
case 0x6d:
|
||||
if (long_op)
|
||||
{
|
||||
*((DWORD *)data) = IO_inport( DX_sig(context), 4);
|
||||
TRACE(io, "0x%x < %08lx @ %04x:%04x\n", DX_sig(context),
|
||||
*((DWORD *)data), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
else
|
||||
{
|
||||
*((WORD *)data) = IO_inport( DX_sig(context), 2);
|
||||
TRACE(io, "0x%x < %04x @ %04x:%04x\n", DX_sig(context),
|
||||
*((WORD *)data), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
break;
|
||||
case 0x6e:
|
||||
IO_outport( DX_sig(context), 1, *((BYTE *)data));
|
||||
TRACE(io, "0x%x > %02x @ %04x:%04x\n", DX_sig(context),
|
||||
*((BYTE *)data), CS_sig(context), IP_sig(context));
|
||||
break;
|
||||
case 0x6f:
|
||||
if (long_op)
|
||||
{
|
||||
IO_outport( DX_sig(context), 4, *((DWORD *)data));
|
||||
TRACE(io, "0x%x > %08lx @ %04x:%04x\n", DX_sig(context),
|
||||
*((DWORD *)data), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
else
|
||||
{
|
||||
IO_outport( DX_sig(context), 2, *((WORD *)data));
|
||||
TRACE(io, "0x%x > %04x @ %04x:%04x\n", DX_sig(context),
|
||||
*((WORD *)data), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -609,45 +629,93 @@ BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context )
|
|||
|
||||
case 0xe4: /* inb al,XX */
|
||||
AL_sig(context) = IO_inport( instr[1], 1 );
|
||||
TRACE(io, "0x%x < %02x @ %04x:%04x\n", instr[1],
|
||||
AL_sig(context), CS_sig(context), IP_sig(context));
|
||||
EIP_sig(context) += prefixlen + 2;
|
||||
return TRUE;
|
||||
|
||||
case 0xe5: /* in (e)ax,XX */
|
||||
if (long_op) EAX_sig(context) = IO_inport( instr[1], 4 );
|
||||
else AX_sig(context) = IO_inport( instr[1], 2 );
|
||||
if (long_op)
|
||||
{
|
||||
EAX_sig(context) = IO_inport( instr[1], 4 );
|
||||
TRACE(io, "0x%x < %08lx @ %04x:%04x\n", instr[1],
|
||||
EAX_sig(context), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
else
|
||||
{
|
||||
AX_sig(context) = IO_inport( instr[1], 2 );
|
||||
TRACE(io, "0x%x < %04x @ %04x:%04x\n", instr[1],
|
||||
AX_sig(context), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
EIP_sig(context) += prefixlen + 2;
|
||||
return TRUE;
|
||||
|
||||
case 0xe6: /* outb XX,al */
|
||||
IO_outport( instr[1], 1, AL_sig(context) );
|
||||
TRACE(io, "0x%x > %02x @ %04x:%04x\n", instr[1],
|
||||
AL_sig(context), CS_sig(context), IP_sig(context));
|
||||
EIP_sig(context) += prefixlen + 2;
|
||||
return TRUE;
|
||||
|
||||
case 0xe7: /* out XX,(e)ax */
|
||||
if (long_op) IO_outport( instr[1], 4, EAX_sig(context) );
|
||||
else IO_outport( instr[1], 2, AX_sig(context) );
|
||||
if (long_op)
|
||||
{
|
||||
IO_outport( instr[1], 4, EAX_sig(context) );
|
||||
TRACE(io, "0x%x > %08lx @ %04x:%04x\n", instr[1],
|
||||
EAX_sig(context), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
else
|
||||
{
|
||||
IO_outport( instr[1], 2, AX_sig(context) );
|
||||
TRACE(io, "0x%x > %04x @ %04x:%04x\n", instr[1],
|
||||
AX_sig(context), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
EIP_sig(context) += prefixlen + 2;
|
||||
return TRUE;
|
||||
|
||||
case 0xec: /* inb al,dx */
|
||||
AL_sig(context) = IO_inport( DX_sig(context), 1 );
|
||||
TRACE(io, "0x%x < %02x @ %04x:%04x\n", DX_sig(context),
|
||||
AL_sig(context), CS_sig(context), IP_sig(context));
|
||||
EIP_sig(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
|
||||
case 0xed: /* in (e)ax,dx */
|
||||
if (long_op) EAX_sig(context) = IO_inport( DX_sig(context), 4 );
|
||||
else AX_sig(context) = IO_inport( DX_sig(context), 2 );
|
||||
if (long_op)
|
||||
{
|
||||
EAX_sig(context) = IO_inport( DX_sig(context), 4 );
|
||||
TRACE(io, "0x%x < %08lx @ %04x:%04x\n", DX_sig(context),
|
||||
EAX_sig(context), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
else
|
||||
{
|
||||
AX_sig(context) = IO_inport( DX_sig(context), 2 );
|
||||
TRACE(io, "0x%x < %04x @ %04x:%04x\n", DX_sig(context),
|
||||
AX_sig(context), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
EIP_sig(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
|
||||
case 0xee: /* outb dx,al */
|
||||
IO_outport( DX_sig(context), 1, AL_sig(context) );
|
||||
TRACE(io, "0x%x > %02x @ %04x:%04x\n", DX_sig(context),
|
||||
AL_sig(context), CS_sig(context), IP_sig(context));
|
||||
EIP_sig(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
|
||||
case 0xef: /* out dx,(e)ax */
|
||||
if (long_op) IO_outport( DX_sig(context), 4, EAX_sig(context) );
|
||||
else IO_outport( DX_sig(context), 2, AX_sig(context) );
|
||||
if (long_op)
|
||||
{
|
||||
IO_outport( DX_sig(context), 4, EAX_sig(context) );
|
||||
TRACE(io, "0x%x > %08lx @ %04x:%04x\n", DX_sig(context),
|
||||
EAX_sig(context), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
else
|
||||
{
|
||||
IO_outport( DX_sig(context), 2, AX_sig(context) );
|
||||
TRACE(io, "0x%x > %04x @ %04x:%04x\n", DX_sig(context),
|
||||
AX_sig(context), CS_sig(context), IP_sig(context));
|
||||
}
|
||||
EIP_sig(context) += prefixlen + 1;
|
||||
return TRUE;
|
||||
|
||||
|
|
Loading…
Reference in New Issue