Interrupts are not working in inline-assembler of C++(i tried VC++ 10, GCC 4, Digital Mars). Is there any interrupt-equivalent windows free-to-access memory areas? How can i reach system properties and video ram?(can i?)
These i would like to know:
mov ah,06h
mov dl,35h
int 21f //would print '5' on screen but it isnt (works in only pure assembler)
and:
mov ax,1500h
mov ch,97h
int 2f //would get me info for the cache-hit number on DI:SI
Thank you
Win32 applications don't call interrupts, they call system services. There's a number of assembly for Windows tutorials on Iczelion's page.
Related
I'm new to C++ programming and have always wanted to write a system information program for MS-DOS. I'm currently using the latest DigiMars C++ compiler and MASM 6.13 for my project. The project settings are for large memory model with a target CPU of an Intel 8088 processor for the widest compatibility with MS-DOS.
I'm attempting to write a routine that checks if the CPU supports the CPUID instruction found on late model 486 and early Pentium CPUs. I found a couple bits of code through Google searches and have been able to add them to the project and successfully compile, but none of them work. The problem is that when I attempt to execute the program I get a message about an invalid instruction (under my Windows NT 3.51 test system) and it completely hangs on my test MS-DOS systems.
The code I'm using is as follows:
public _is_cpuid_supported
cpuid macro
db 0fh, 0a2h
endm
_is_cpuid_supported proc near
.486
push bp
mov bp, sp
sub sp, 40
push eax
push ebx
pushfd ; get extended flags
pop eax
mov ebx, eax ; save current flags
xor eax, 200000h ; toggle bit 21
push eax ; put new flags on stack
popfd ; flags updated now in flags
pushfd ; get extended flags
pop eax
xor eax, ebx ; if bit 21 r/w then eax <> 0
pop ebx
pop eax
je no_cpuid ; can't toggle id bit 21, no cpuid here
mov ax, 1 ; cpuid supported
jmp done_cpuid_sup
no_cpuid:
mov ax, 0 ; cpuid not supported
done_cpuid_sup:
mov sp, bp
pop bp
ret
_is_cpuid_supported endp
I've also tried the sample from OSDev.org here: https://wiki.osdev.org/CPUID?msclkid=3c6e16f9c23611ec98be59859d0dd887 but it doesn't work either. Any tips? Let me know if further clarification is needed.
In large memory model DOS programs, the default for assembly procedures is far. Removing the near keyword from the line _is_cpuid_supported proc near solved the problem. Thanks to #MichaelPetch for the tip.
I have a service with code that runs for years.
Now using the VS-2019 16.3.7/8/9 I get a 0xC000001D (The thread tried to execute an invalid instruction.) exceptions on the first floating point arithmetic in the boot phase of the service on some machines.
Installing the same code base compiled with 16.2.4/5 works.
I have a full memory crash dump from one machine. The crash happens on a call to _dtol3.
I can see in the assembly code this situation.
0149477B 83 3D B4 AC 55 01 06 cmp dword ptr [__isa_available (0155ACB4h)],6
01494782 7C 15 jl _dtol3_default (01494799h)
01494784 C5 FA 7E C0 vmovq xmm0,xmm0
01494788 62 F1 FD 08 7A C0 vcvttpd2qq xmm0,xmm0 <---- CRASH
__isa_available has the value 6. On my machine the value is 5. One machine were we can see the crash is a XEON Silver 4110 running our software virtualized. Same exe runs on a XEON E5-2620. The same exe runs on all my client machines in my company without any problem (a mix of old and new Intel machines).
Looking at the called code, I can see that there is a simple difference and division of to double values comparing it to a value greater or equal 1.0.
COleDateTime nowClient = COleDateTime::GetCurrentTime(),
nowDB = GetCurrentTime();
COleDateTimeSpan diff = nowDB-nowClient;
if (diff.GetTotalMinutes()>=1) // <----- CRASH
...
Is there any way to influence the code creation in the VS to avoid the calls to this code? (Any shim, compatibility setting)
Is there any known change in VS-2019 that influences the floating math since VS 16.2.4, that might has influence on my problem?
This is a bug in the 16.3.x update of Visual Studio. Here is a link to the bug report.
Read it carefully, it actually happens on machines that support AVX512, not older CPUs as the initial post describes. This also contains a couple of workarounds to avoid the issue until Microsoft has a fix.
You can enable or disable the generation of 'advanced' instructions for each project in its "Properties" sheet:
Right click the project in the Solution Explorer and select "Properties" from the pop-up menu.
Select/Open the "C/C++" tab in the left-hand pane and then select the "Code Generation" item.
In the list of properties then presented in the right-hand pane, select "Not Set" for the "Enabled Enhanced Instruction Set" property (or whichever option will give you code that is compatible with your target PCs).
The compiler's use of vmovq implies that you have (at least) "Advanced Vector Extensions" enabled; also, I think (not 100% sure) that vcvttpd2qq is in the "AVX2" category.
I'm hooking into IAudioClient and IAudioRenderClient to retrieve the raw audio buffer. To determine the format I call GetMixFormat on the client before. This works fine for most applications like games or Flash Player in Firefox.
However, audio captured from Google Chrome (Flash) is distorted. I've attached a short sample of the same audio stream captured from Firefox and Google Chrome. GetMixFormat() reports IEEE_FLOAT, 2 channels at 48k for both. But when importing them in Audacity and using those parameters, only the Firefox one plays well. In fact, to get the graph looking correctly on the Chrome one, I have to import it as Signed PCM (still distorted though).
Any ideas why GetMixFormat is wrong or what format the Google Chrome snippet is using?
As a side note, I found out that the Chrome sample contains 1 full frame (0xF00 bytes) and then only half a frame (0x780 bytes) and the rest filled with zeros, even though the functions report to have written 0xF00 bytes. But even when removing that zero data, I can't get anywhere. Is Chrome somehow altering the buffer?
Files:
http://lms-dev.com/files/so/audio_ff.raw
http://lms-dev.com/files/so/audio_chrome.raw
http://lms-dev.com/files/so/audio_chrome_skip_empty_frame.raw
Any help is much appreciated! Thanks in advance.
Okay I kind of fixed the issue with GetMixFormat by directly reading the WAVEFORMATEX from the audio client instance. It's version dependent though... This is how it works for Win 8:
mov eax, pAudioClient
mov eax, [eax + 0x7C]
mov eax, [eax + 0x3C]
mov edi, eax
mov eax, [edi - 50h]
add eax, 0xA0
mov waveFormatEx, eax
This also got me the correct frame size, which was my core issue when grabbing the buffer. Playing it in 16bit PCM mode works fine now.
I tried to adapt it to Win 7, but the Audioses.dll differs a lot, so this might take some more time.
In assembly we use the org instruction to set the location counter to a specific location in the memory. This is particularly helpful in making Operating Systems. Here's an example boot loader (From wikibooks):
org 7C00h
jmp short Start ;Jump over the data (the 'short' keyword makes the jmp instruction smaller)
Msg: db "Hello World! "
EndMsg:
Start: mov bx, 000Fh ;Page 0, colour attribute 15 (white) for the int 10 calls below
mov cx, 1 ;We will want to write 1 character
xor dx, dx ;Start at top left corner
mov ds, dx ;Ensure ds = 0 (to let us load the message)
cld ;Ensure direction flag is cleared (for LODSB)
Print: mov si, Msg ;Loads the address of the first byte of the message, 7C02h in this case
;PC BIOS Interrupt 10 Subfunction 2 - Set cursor position
;AH = 2
Char: mov ah, 2 ;BH = page, DH = row, DL = column
int 10h
lodsb ;Load a byte of the message into AL.
;Remember that DS is 0 and SI holds the
;offset of one of the bytes of the message.
;PC BIOS Interrupt 10 Subfunction 9 - Write character and colour
;AH = 9
mov ah, 9 ;BH = page, AL = character, BL = attribute, CX = character count
int 10h
inc dl ;Advance cursor
cmp dl, 80 ;Wrap around edge of screen if necessary
jne Skip
xor dl, dl
inc dh
cmp dh, 25 ;Wrap around bottom of screen if necessary
jne Skip
xor dh, dh
Skip: cmp si, EndMsg ;If we're not at end of message,
jne Char ;continue loading characters
jmp Print ;otherwise restart from the beginning of the message
times 0200h - 2 - ($ - $$) db 0 ;Zerofill up to 510 bytes
dw 0AA55h ;Boot Sector signature
;OPTIONAL:
;To zerofill up to the size of a standard 1.44MB, 3.5" floppy disk
;times 1474560 - ($ - $$) db 0
Is it possible accomplish the task with C++? Is there any command, function etc. like org where i can change the location of the program?
No it's not possible to do in any C compiler that I know of. You can however create your own linker script that places the code/data/bss segments at specific addresses.
Just for clarity, the org directive does not load the code at the specified address, it merely informs the assembler that the code will be loaded at that address. The code shown appears to be for Nasm (or similar) - in AT&T syntax, the .org directive does something different: it pads the code to that address - similar to the times line in the Nasm code.. Nasm can do this because in -f bin mode, it "acts as it's own linker".
The important thing for the code to know is the address where Msg can be found. The jmps and jnes (and call and ret which your example doesn't have, but a compiler may generate) are relative addressing mode. We code jmp target but the bytes that are actually emitted say jmp distance_to_target (plus or minus) so the address doesn't matter.
Gas doesn't do this, it emits a linkable object file. To use ld without a linker script the command line looks something like:
ld -o boot.bin boot.o -oformat binary -T text=0x7C00
(don't quote me on that exact syntax but "something like that") If you can get a linkable object file from your (16-bit capable!) C++ compiler, you might be able to do the same.
In the case of a bootsector, the code is loaded by the BIOS (or fake BIOS) at 0x7C00 - one of the few things we can assume about the bootsector. The sane thing for a bootsector to do is not fiddle-faddle around printing a message, but to load something else. You'll need to know how to find the something else on the disk and where you want to load it to (perhaps where your C++ compiler wants to put it by default) - and jmp there. This jmp will want to be a far jmp, which does need to know the address.
I'm guessing it's going to be some butt-ugly C++!
I'm currently working on hooking ntdll.dll calls via dll injection.
At first, I create thread in existing process via CreateRemoteThread() then I load my dll via LoadLibrary and finally hook calls on PROCESS_ATTACH.
Injection works fine, but then I want to log all registry and file system queries. And the problem is that it doesn't work properly.
I decided to publish code via PasteBin, because piece is pretty big. Here is the link:
http://pastebin.com/39r4Me6B
I'm trying to hook ZwOpenKey, then log key content and then launch "true" function by pointer. Function NOpenKey gets executed, but process stops without any errors.
Does anyone see any issues?
If you use OllyDbg, ZwOpenKey starts with 5 bytes MOV EAX, 77.
You can overwrite these bytes like so JMP _myZwOpenKey then from there you can do whatever with the values on the stack, restore all registers then do a JMP 7C90D5B5 which is address of ZwOpenKey + 5 bytes.
CPU Disasm
Address Hex dump Command Comments
7C90D5AF 90 NOP
7C90D5B0 /$ B8 77000000 MOV EAX,77 ; ntdll.ZwOpenKey(guessed rg1,Arg2,Arg3)
7C90D5B5 |. BA 0003FE7F MOV EDX,7FFE0300
7C90D5BA |. FF12 CALL DWORD PTR DS:[EDX]
7C90D5BC \. C2 0C00 RETN 0C
I usually do these in Assembly that way I don't have to mess around a lot with type casting and all that. Hope this helps.