I need help compiling the source code for Quake III Arena. I'm using the version provided by ID Software's Github account (https://github.com/id-Software/Quake-III-Arena). I'm trying to compile it in VS2015, is that a problem? It converts the project without any issues. However, when I compile, all I get is a black screen and a messed up color scheme. The debugger tells me the problem is in this funcion:
#ifdef _WIN32
__asm {
pushad
mov esi, programStack;
mov edi, opStack
call entryPoint
mov programStack, esi
mov opStack, edi
popad
}
More precisely, in the line mov programStack, esi. Any ideas? I'm trying to make a game with this engine, since it's basically the "mother" of all Fpses today :D
Any help is appreciated.
Make sure to clean all the projects in VS2015, and to the quake3 project add the following command line agruments:
+set sv_pure 0 +set vm_game 0 +set vm_cgame 0 +set vm_ui 0
Also, make sure to copy the baseq3 folder from your Quake 3 arena game into the Quake-III-Arena/code folder.
Related
According to this post, in x64, you can perform lea rax, [rip] to get the current instruction. How would I do this using asmjit?
I figured out the solution: assembler.lea(asmjit::x86::rax, asmjit::x86::ptr(asmjit::x86::rip));
A quick question here:
I'm trying to experiment with inline assembly using Embarcadero C++ Builder XE3 on 32-bit Windows 7, specifically to start re-teaching myself assembly with the possibility of future pragmatic application.
So far I've been able to write a set of instructions within a simple console project which compiles fine using all C++ Builder syntax at my disposal:
int _tmain(int argc, _TCHAR* argv[]) {
_asm{
mov dl, 0x24
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
mov dl, 0x25
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
mov dl, 0x26
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
mov dl, 0x27
mov ah, 2 // Print character
int 0x21 // Dos Interrupt - Run operation in AH
int 0x20 // terminate COM
}
return 0;
}
This compiles ok, and these instructions work straight in NASM and the Windows native DEBUG environment. What I expect is a simple write to the console: $%&' followed by a successful termination.
However, when I try to run Project1.exe via the command line I immediately get a standard Win7 runtime error popup which disappears after a few seconds and terminates the program.
Running with debugging, I seem to be successfully reaching the first int 0x21 before it hangs, at which point Borland gives me the message:
Project Project1.exe raised exception class $C00000005 with message 'access violation at 0x00401213: read of address 0xffffffff'.
My theory is that I'm not properly initializing the segment with a 256-byte offset (NASM would use something like org 0x100 at the beginning of the instruction set). But I'm not entirely sure that's the issue.
Any ideas?
Those int 0x21 instructions are for MS-DOS and not Windows. They mean something else in a Windows program, with the result that you go up in flames.
I work primarily in C++ Builder, But I've also programmed assembly and nasm for production code (mainly on micros). My recommendation is not to go near C++ builder for anything you don't have to. Learning can be an art and the way you go about learning has a lot to do with the outcome. C++ Builder integration with assembly is a detour through South Compton. Even though it may not be the way you normally work, it will pay off big time to learn nasm in pure command line.
I suspect that we've run into a compiler bug in VS2013. Setting a single breakpoint actually inserts a breakpoint into two different addresses of the code.
I set a breakpoint on line 89 of a source file (MessageServerManager.cpp). Here is a snippet of that part of the code (a normal method in a class):
87: void MessageServerManager::setup_dsp_emulation()
88: {
89: auto dsp_emulation_setting = util::get_env_var("DSP_EMULATION");
90: _emulating_dsp = !dsp_emulation_setting.empty();
91:
92: if (_emulating_dsp)
When I do this, a single breakpoint appears in VS2013's breakpoint window. However, when the code is built and executed (with optimizations turned off, by the way), the view changes to the following:
Notice that the two breakpoints are at different addresses. When the first breakpoint is hit, the highlighted line in VS is line 89, but when viewing the disassembly, it's actually in another piece of code (the object's constructor).
Since it's in the objects constructor, it's probably a good idea to share how this object is created. It's a singleton that basically looks like the following:
class MessageServerManager : public boost::basic_lockable_adapter < std::recursive_mutex >
{
public:
inline static MessageServerManager& instance() { static MessageServerManager manager; return manager; }
void start_dsp_facing_server();
private:
MessageServerManager();
}
And the very first time we're accessing MessageServerManager, we're calling start_dsp_facing_server() (it's one of the first few lines of main()):
MessageServerManager::instance().start_dsp_facing_server();
The following is the disassembled code of the breakpoint that's in the incorrect location. The C++ code shown is the method the breakpoint should be set on (start_dsp_facing_server()), but the disassembled code is obviously different (it's the constructor):
87: void MessageServerManager::setup_dsp_emulation()
88: {
89: auto dsp_emulation_setting = util::get_env_var("DSP_EMULATION");
011AAB8F push 0
011AAB91 mov ecx,dword ptr [this]
011AAB94 add ecx,8
011AAB97 call std::shared_ptr<messaging::IMessageServer>::shared_ptr<messaging::IMessageServer> (010619C9h)
011AAB9C mov byte ptr [ebp-4],1
90: _emulating_dsp = !dsp_emulation_setting.empty();
011AABA0 push 0
011AABA2 mov ecx,dword ptr [this]
011AABA5 add ecx,10h
011AABA8 call std::unique_ptr<radian::SimpleThread,std::default_delete<radian::SimpleThread> >::unique_ptr<radian::SimpleThread,std::default_delete<radian::SimpleThread> > (0106E5CAh)
011AABAD mov byte ptr [ebp-4],2
91:
92: if (_emulating_dsp)
93: {
If I look at the disassembly of the other location of the breakpoint, that part also shows a line 89, but it's the right disassembly.
This is in VS2013 update 4, C++ native application, linked against Boost 1.56.0 and Qt 5.3.1, 32-bit.
Has anyone seen this before, know potential causes, and possible solutions?
I've seen this question (and the suggestion about line endings), and I'm aware that optimizations can reorder code and cause odd debugger behavior, but I've batch converted my files to ensure they have proper line endings, and we have optimizations turned off.
I would post a minimal example that shows this behavior, but I'm not able to reproduce this on demand with other code.
I am trying to export a .dll file and trying to use it in my c# application to write a data to a port. In my .cpp file (to create a .dll) if I use "out" command it gives "error C2415: improper operand type" error message. Do you have any idea why i cannot use this "out" command? ("mov" command is working well btw)
See my code below:
#include <stdio.h>
extern "C" __declspec(dllexport) void enableWatchDog()
_asm {
out 66,41
out 62,4
}
}
out has six forms:
out imm8, AL
out imm8, AX
out imm8, EAX
out DX, AL
out DX, AX
out DX, EAX
Your usages match none of them. Perhaps this would work (not tested):
mov al, 41
out 66, al
mov al, 4
out 62, al
I don't have too much experience with IO ports on x86, but from what I've been able to find, 66 and 62 seem a little suspicious to me. Shouldn't they be 66h and 62h? 41h (could be two flags set, or ASCII 'A') also makes a little more sense to me than 41 (a rather arbitrary number).
Assembly is not a high level language, where you can plug an arbitrary expression anywhere. The out command can only take an Ax register for a second operand, where Ax means AL, AX, or EAX. So reformulate like this:
mov al, 41
out 66, al
mov al, 4
out 62, al
The out command is privileged; it only works in kernel level drivers on Windows, trying to do it in a regular program will get you an "Invalid operation" error.
What target platform are you using for your C++ dll? You need to compile to x86 code, not CLR.
I've got a software application which some users report reliably crashes in certain situations. I can't reproduce it on any of the machines I've got so I'm feeling pretty stuck as to how to solve it.
A user posted me the assembly line where the crash happens, like this:
00505e58 1000 adc [eax],al
00505e5a cc int 3
00505e5b cc int 3
00505e5c cc int 3
00505e5d cc int 3
00505e5e cc int 3
00505e5f cc int 3
00505e60 55 push ebp
00505e61 8bec mov ebp,esp
00505e63 83ec1c sub esp,0x1c
FAULT -> 00505e66 ff4f08 dec dword ptr [edi+0x8] ds:0023:00000008=????????
00505e69 53 push ebx
00505e6a 56 push esi
00505e6b 0f85b0000000 jne Construct2+0x105f21 (00505f21)
00505e71 8d9894010000 lea ebx,[eax+0x194]
00505e77 8d45f0 lea eax,[ebp-0x10]
00505e7a 8bcb mov ecx,ebx
00505e7c e8ef4ff1ff call Construct2+0x1ae70 (0041ae70)
00505e81 8d45e4 lea eax,[ebp-0x1c]
00505e84 8bcb mov ecx,ebx
00505e86 e88580fdff call Construct2+0xddf10 (004ddf10)
I'm using Visual Studio 2010 and have my .pdbs for the build I gave the user. Is it possible to turn this assembly trace in to the faulting code line?
If you could get a full crash dump of your app when it crashes, then you could bring up the dmp in either windbg or Visual Studio and debug with source code rather easily. There's plenty of info on the web for getting a dump and debugging. For example, if you have a dump and matching pdb and bring thsi up in windbg, you can just do a ".lines" and see exactly where this is happening.
If you don't have a dump, then one way to do this is to run your app locally and look at the code at this address. It looks like your app, which I'm assuming is Construct2.exe, starts off at a base address of 0x0040000 and you're crashing at 0x00505E66 where EDI is 0. So if you flip to diassembly view, go to this address (or set a bp) then look at the source and you're good to go.