Floating operations. Is there loop-carried dependency? - optimization

The following code presents QuickSort. I am trying to make it faster. Please help.
global sort
sort:
push ebp
mov ebp, esp
push edi
push esi
push ebx
sub esp, 28
mov eax, dword [ebp+8]
mov esi, dword [ebp+12]
mov dword [ebp-32], 1
lea edi, [eax-1]
sal eax, 2
lea edx, [eax+18]
movss xmm1, dword [esi-4+eax]
mov dword [ebp-28], edi
and edx, -16
sub esp, edx
lea edx, [esp+3]
shr edx, 2
lea ebx, [0+edx*4]
mov dword [4+edx*4], edi
mov dword [0+edx*4], 0
xor edi, edi
mov dword [ebp-36], ebx
.L14:
mov eax, dword [ebp-28]
lea edx, [edi-1]
cmp eax, edi
lea ebx, [esi+eax*4]
jle .L15
lea eax, [esi+edi*4]
.L18:
movss xmm0, dword [eax]
comiss xmm1, xmm0
jb .L16
add edx, 1
lea ecx, [esi+edx*4]
movss xmm2, dword [ecx]
movss dword [ecx], xmm0
movss dword [eax], xmm2
.L16:
add eax, 4
cmp eax, ebx
jne .L18
movss xmm1, dword [ebx]
.L15:
lea eax, [esi+4+edx*4]
cmp edx, edi
movss xmm0, dword [eax]
movss dword [eax], xmm1
movss dword [ebx], xmm0
jg .L19
sub dword [ebp-32], 2
lea edi, [edx+2]
cmp edi, dword [ebp-28]
jl .L25
.L21:
mov eax, dword [ebp-32]
test eax, eax
js .L11
mov edi, dword [ebp-36]
lea eax, [edi+eax*4]
mov edi, dword [eax]
mov ecx, edi
mov dword [ebp-28], edi
mov edi, dword [eax-4]
movss xmm1, dword [esi+ecx*4]
jmp .L14
.L19:
mov edi, dword [ebp-32]
mov eax, dword [ebp-36]
mov dword [eax+edi*4], edx
lea edi, [edx+2]
cmp edi, dword [ebp-28]
jge .L21
.L25:
mov ebx, dword [ebp-32]
mov ecx, dword [ebp-36]
movaps xmm1, xmm0
lea eax, [ecx+ebx*4]
mov ecx, dword [ebp-28]
mov dword [eax+4], edi
mov dword [eax+8], ecx
mov eax, ebx
add eax, 2
mov dword [ebp-32], eax
jns .L14
.L11:
lea esp, [ebp-12]
pop ebx
pop esi
pop edi
pop ebp
ret

Related

Executing function in other process through dll injection

I'm trying to execute a function in a VB6 app, I already know the instruction address and the format of the original code but when I execute it the app crashes.
It's probably wrong the way I'm executing it or there is something else missing.
This is the "original" function code:
Public Sub WriteLeftClick(ByVal x As Byte, ByVal y As Byte)
On Error GoTo WriteLeftClick_Err
With outgoingData
Call .WriteByte(ClientPacketID.LeftClick)
Call .WriteByte(x)
Call .WriteByte(y)
End With
Exit Sub
WriteLeftClick_Err:
Call RegistrarError(Err.number, Err.Description, "Protocol.WriteLeftClick", Erl)
Resume Next
End Sub
This is the decompiled version from the exe:
Private Sub Proc_98_29_793220(arg_C) '793220
loc_00793220: push ebp
loc_00793221: mov ebp, esp
loc_00793223: sub esp, 00000018h
loc_00793226: push 0042B2B6h ; __vbaExceptHandler
loc_0079322B: mov eax, fs:[00000000h]
loc_00793231: push eax
loc_00793232: mov fs:[00000000h], esp
loc_00793239: sub esp, 00000034h
loc_0079323C: push ebx
loc_0079323D: push esi
loc_0079323E: push edi
loc_0079323F: mov var_18, esp
loc_00793242: mov var_14, 00425FD8h
loc_00793249: xor edi, edi
loc_0079324B: mov var_10, edi
loc_0079324E: mov var_C, edi
loc_00793251: mov var_24, edi
loc_00793254: mov var_28, edi
loc_00793257: mov var_2C, edi
loc_0079325A: mov var_30, edi
loc_0079325D: mov var_4, 00000001h
loc_00793264: mov var_4, 00000002h
loc_0079326B: push 00000001h
loc_0079326D: call [00401134h] ; __vbaOnError
loc_00793273: mov var_4, 00000003h
loc_0079327A: mov eax, [007CE9C4h]
loc_0079327F: mov esi, [eax]
loc_00793281: mov ecx, 00000016h
loc_00793286: call [00401204h] ; __vbaI2I4
loc_0079328C: push eax
loc_0079328D: mov ecx, [007CE9C4h]
loc_00793293: push ecx
loc_00793294: call [esi+00000030h]
loc_00793297: fnclex
loc_00793299: cmp eax, edi
loc_0079329B: jge 007932B6h
loc_0079329D: push 00000030h
loc_0079329F: push 00484EA0h
loc_007932A4: mov edx, [007CE9C4h]
loc_007932AA: push edx
loc_007932AB: push eax
loc_007932AC: mov esi, [004010E0h] ; __vbaHresultCheckObj
loc_007932B2: call __vbaHresultCheckObj
loc_007932B4: jmp 007932BCh
loc_007932B6: mov esi, [004010E0h] ; __vbaHresultCheckObj
loc_007932BC: mov var_4, 00000004h
loc_007932C3: mov eax, [007CE9C4h]
loc_007932C8: mov ecx, [eax]
loc_007932CA: mov edx, arg_8
loc_007932CD: push edx
loc_007932CE: push eax
loc_007932CF: call [ecx+0000002Ch]
loc_007932D2: fnclex
loc_007932D4: cmp eax, edi
loc_007932D6: jge 007932E9h
loc_007932D8: push 0000002Ch
loc_007932DA: push 00484EA0h
loc_007932DF: mov ecx, [007CE9C4h]
loc_007932E5: push ecx
loc_007932E6: push eax
loc_007932E7: call __vbaHresultCheckObj
loc_007932E9: mov var_4, 00000005h
loc_007932F0: mov eax, [007CE9C4h]
loc_007932F5: mov edx, [eax]
loc_007932F7: mov ecx, arg_C
loc_007932FA: push ecx
loc_007932FB: push eax
loc_007932FC: call [edx+0000002Ch]
loc_007932FF: fnclex
loc_00793301: cmp eax, edi
loc_00793303: jge 00793316h
loc_00793305: push 0000002Ch
loc_00793307: push 00484EA0h
loc_0079330C: mov edx, [007CE9C4h]
loc_00793312: push edx
loc_00793313: push eax
loc_00793314: call __vbaHresultCheckObj
loc_00793316: mov var_4, 00000006h
loc_0079331D: mov eax, [007CE0ACh]
loc_00793322: add eax, 00000001h
loc_00793325: jo 007934A1h
loc_0079332B: mov [007CE0ACh], eax
loc_00793330: mov var_4, 00000007h
loc_00793337: mov ecx, [007CE9C4h]
loc_0079333D: mov edx, [ecx]
loc_0079333F: push eax
loc_00793340: push ecx
loc_00793341: call [edx+00000034h]
loc_00793344: fnclex
loc_00793346: cmp eax, edi
loc_00793348: jge 0079335Bh
loc_0079334A: push 00000034h
loc_0079334C: push 00484EA0h
loc_00793351: mov ecx, [007CE9C4h]
loc_00793357: push ecx
loc_00793358: push eax
loc_00793359: call __vbaHresultCheckObj
loc_0079335B: mov var_4, 00000008h
loc_00793362: mov edx, [007CE9C4h]
loc_00793368: push edx
loc_00793369: lea eax, var_28
loc_0079336C: push eax
loc_0079336D: call [00401148h] ; __vbaObjSetAddref
loc_00793373: push eax
loc_00793374: call 007B8560h
loc_00793379: lea ecx, var_28
loc_0079337C: call [00401438h] ; __vbaFreeObj
loc_00793382: call [00401118h] ; __vbaExitProc
loc_00793388: push 0079348Eh
loc_0079338D: jmp 0079348Dh
loc_00793392: mov var_4, 00000009h
loc_00793399: mov eax, [007CE9C4h]
loc_0079339E: mov ecx, [eax]
loc_007933A0: push eax
loc_007933A1: call [ecx+0000000Ch]
loc_007933A4: fnclex
loc_007933A6: test eax, eax
loc_007933A8: jge 007933BFh
loc_007933AA: push 0000000Ch
loc_007933AC: push 00484EA0h
loc_007933B1: mov edx, [007CE9C4h]
loc_007933B7: push edx
loc_007933B8: push eax
loc_007933B9: call [004010E0h] ; __vbaHresultCheckObj
loc_007933BF: mov var_4, 0000000Ah
loc_007933C6: mov edi, [00401370h] ; rtcErrObj
loc_007933CC: call edi
loc_007933CE: push eax
loc_007933CF: lea eax, var_28
loc_007933D2: push eax
loc_007933D3: mov ebx, [00401138h] ; __vbaObjSet
loc_007933D9: call ebx
loc_007933DB: mov esi, eax
loc_007933DD: mov ecx, [esi]
loc_007933DF: lea edx, var_30
loc_007933E2: push edx
loc_007933E3: push esi
loc_007933E4: call [ecx+0000001Ch]
loc_007933E7: fnclex
loc_007933E9: test eax, eax
loc_007933EB: jge 007933FCh
loc_007933ED: push 0000001Ch
loc_007933EF: push 00455DF4h
loc_007933F4: push esi
loc_007933F5: push eax
loc_007933F6: call [004010E0h] ; __vbaHresultCheckObj
loc_007933FC: call edi
loc_007933FE: push eax
loc_007933FF: lea eax, var_2C
loc_00793402: push eax
loc_00793403: call ebx
loc_00793405: mov esi, eax
loc_00793407: mov ecx, [esi]
loc_00793409: lea edx, var_24
loc_0079340C: push edx
loc_0079340D: push esi
loc_0079340E: call [ecx+0000002Ch]
loc_00793411: fnclex
loc_00793413: test eax, eax
loc_00793415: jge 00793426h
loc_00793417: push 0000002Ch
loc_00793419: push 00455DF4h
loc_0079341E: push esi
loc_0079341F: push eax
loc_00793420: call [004010E0h] ; __vbaHresultCheckObj
loc_00793426: call [004012A0h] ; rtcGetErl
loc_0079342C: mov ecx, eax
loc_0079342E: call [00401204h] ; __vbaI2I4
loc_00793434: push eax
loc_00793435: push 00486528h ; "Argentum20.Protocol_Writes.WriteLeftClick"
loc_0079343A: mov eax, var_24
loc_0079343D: push eax
loc_0079343E: mov ecx, var_30
loc_00793441: push ecx
loc_00793442: call 0066E230h
loc_00793447: lea ecx, var_24
loc_0079344A: call [00401434h] ; __vbaFreeStr
loc_00793450: lea edx, var_2C
loc_00793453: push edx
loc_00793454: lea eax, var_28
loc_00793457: push eax
loc_00793458: push 00000002h
loc_0079345A: call [00401098h] ; __vbaFreeObjList
loc_00793460: add esp, 0000000Ch
loc_00793463: call [00401118h] ; __vbaExitProc
loc_00793469: push 0079348Eh
loc_0079346E: jmp 0079348Dh
loc_00793470: lea ecx, var_24
loc_00793473: call [00401434h] ; __vbaFreeStr
loc_00793479: lea ecx, var_2C
loc_0079347C: push ecx
loc_0079347D: lea edx, var_28
loc_00793480: push edx
loc_00793481: push 00000002h
loc_00793483: call [00401098h] ; __vbaFreeObjList
loc_00793489: add esp, 0000000Ch
loc_0079348C: ret
loc_0079348D: ret
loc_0079348E: mov ecx, var_20
loc_00793491: mov fs:[00000000h], ecx
loc_00793498: pop edi
loc_00793499: pop esi
loc_0079349A: pop ebx
loc_0079349B: mov esp, ebp
loc_0079349D: pop ebp
loc_0079349E: retn 0008h
End Sub
And this is the code I'm using for my DLL:
#include <windows.h>
#include "Memory.h"
#include <sstream>
typedef void(__stdcall* myFunc)(byte, byte);
myFunc func;
DWORD WINAPI MainThread(LPVOID param) {
//func = (myFunc)(0x793220);
//typedef int func(byte x, byte y); // Creating an int function alias, replace (void) with your parameters
uintptr_t modBase = (uintptr_t)GetModuleHandle(NULL);
//func* f = (func*)reinterpret_cast<void*>(modBase + 0x393220);
func = (myFunc)(modBase + 0x393220);
HANDLE hPipe;
char buffer[1024];
DWORD dwRead;
/*int value = modBase + 0x393220;
std::stringstream stream;
stream << "Value is " << value;
MessageBoxA(NULL, stream.str().c_str(), "Test Msg", MB_OK | MB_ICONINFORMATION);*/
hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\Pipe"),
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
1,
1024 * 16,
1024 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
while (hPipe != INVALID_HANDLE_VALUE)
{
if (ConnectNamedPipe(hPipe, NULL) != FALSE) // wait for someone to connect to the pipe
{
while (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &dwRead, NULL) != FALSE)
{
/* add terminating zero */
buffer[dwRead] = '\0';
/* do something with data in buffer */
//printf("%s", buffer);
func(55,55);
MessageBoxA(NULL, buffer, "Test Msg", MB_OK | MB_ICONINFORMATION);
}
}
DisconnectNamedPipe(hPipe);
}
FreeLibraryAndExitThread((HMODULE)param, 0);
return 0;
}
BOOL APIENTRY DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
MessageBoxA(NULL, "Hello From The Injected DLL", "Injected !", MB_OK | MB_ICONINFORMATION);
CreateThread(NULL, NULL, MainThread, hInstDLL, NULL, NULL);
break;
case DLL_THREAD_ATTACH:
MessageBoxA(NULL, "Hello From The Injected DLL", "Injected !", MB_OK | MB_ICONINFORMATION);
break;
case DLL_THREAD_DETACH:
MessageBoxA(NULL, "Hello Again From The Injected DLL", "Injected !", MB_OK | MB_ICONINFORMATION);
break;
case DLL_PROCESS_DETACH:
MessageBoxA(NULL, "Hello Again From The Injected DLL", "Injected !", MB_OK | MB_ICONINFORMATION);
break;
}
return TRUE;
}
So basically when it receives a message from the Pipe it should execute that function.
func* f = (func*)reinterpret_cast<void*>(0x793220);
f(55,55);
But when I execute it, the app crashes.
Any ideas?
Finally I got it working.
But I had to change completly the perspective.
Instead of injecting a C++ dll into the game, I created an injector that launches the game, creates a VB object using "CreateVBObjectInThread" and with that using a placeholder for the function and the real address of the pointer I could execute the function in the game and avoid the crash due to the "On error".
Both DLLs now are developed in VB6 as well.

How to inform the optimizer that NonZeroU32::get will never return zero?

Here's the code sample where I ran into the problem:
pub fn div(x: u32, y: u32) -> u32 {
x / y
}
pub fn safe_div(x: u32, y: std::num::NonZeroU32) -> u32 {
x / y.get() // an unchecked division expected
}
Godbolt's rustc 1.47.0 -O generates the same assembly for both functions:
example::div:
push rax
test esi, esi
je .LBB0_2
mov eax, edi
xor edx, edx
div esi
pop rcx
ret
.LBB0_2:
lea rdi, [rip + str.0]
lea rdx, [rip + .L__unnamed_1]
mov esi, 25
call qword ptr [rip + core::panicking::panic#GOTPCREL]
ud2
example::safe_div:
push rax
test esi, esi
je .LBB1_2
mov eax, edi
xor edx, edx
div esi
pop rcx
ret
.LBB1_2:
lea rdi, [rip + str.0]
lea rdx, [rip + .L__unnamed_2]
mov esi, 25
call qword ptr [rip + core::panicking::panic#GOTPCREL]
ud2
However, it is statically known that
checking NonZeroU32::get's result against zero is pointless.
Can I somehow make the optimizer believe it
(maybe with creating new structs for this) in an unsafeless way?
Related GitHub issue #49572
After I saw your question, I added the needed impls to std,
so now the nightly release (and the upcoming 1.51 stable release) supports this!
Godbolt for
pub fn div(x: u32, y: u32) -> u32 {
x / y
}
pub fn safe_div(x: u32, y: std::num::NonZeroU32) -> u32 {
x / y
}
pub fn safe_rem(x: u32, y: std::num::NonZeroU32) -> u32 {
x % y
}
Produces the expected assembly:
example::div:
push rax
test esi, esi
je .LBB0_2
mov eax, edi
xor edx, edx
div esi
pop rcx
ret
.LBB0_2:
lea rdi, [rip + str.0]
lea rdx, [rip + .L__unnamed_1]
mov esi, 25
call qword ptr [rip + core::panicking::panic#GOTPCREL]
ud2
example::safe_div:
mov eax, edi
xor edx, edx
div esi
ret
example::safe_rem:
mov eax, edi
xor edx, edx
div esi
mov eax, edx
ret

Accessing/Adding to a 2D C++ array using inline assembly

I'm trying to create an encryption/decryption program using c++ and assembly. I was originally using 3 different arrays, the original string, the encrypted string, and the decrypted string. I'm now trying to convert this to a 2D array and I'm having trouble adding an encrypted character to the second line of the array.
__asm
{
push eax
push ebx
push ecx
push edx
xor ebx, ebx
jmp checkend
forloop1: add ebx, 1
checkend: cmp ebx, aLength
jge endfor1
movzx ecx, byte ptr[Chars + ebx]
lea eax, EKey
push ecx
mov edi, eax
movzx eax, byte ptr[eax]
and eax, 0x3f
rol al, 1
mov byte ptr[edi], al
cmp eax, 0x00
jnz zerocheck
mov eax, 0x09
zerocheck:mov edx, eax
pop eax
sub eax, edx
rol al, 1
not al
mov byte ptr [Chars + ebx * 2], al // this line here
jmp forloop1
endfor1:
pop edx
pop ecx
pop ebx
pop eax
}
return;
I can read in the first row fine, which is where the string entered is stored. I've marked the line where I'm trying to get the encrypted character to be stored in the second line the array but everything I've tried doesn't seem to work. The [Chars + ebx * 2] is what isn't working. I know that the 2 on the end isn't the correct value, can anyone tell me what value I should be adding/multiplying on the end to get to the second line of the array. Any help would be appreciated.
Managed to get this working. All I had to do was add this line of code first;
mov edx, aLength
Where aLength is the length of the array, and then use that to get the second line in the array like so;
mov byte ptr [Chars + ebx + edx], al

Objective C selector table functions

I am trying to figure out which method objc_msgSend() will call.
While looking at assembly of any function in Appkit or Cocoa or Any framework based on Objective-C framework, I always get stucked at objc_msgSend().
Does any one has any idea how to reach the actual function call from here?
I remember while browsing I have seen some open source code which was kind of Map for which function will be called based on selector (integer value). I guess it was from Apple (not sure). I am trying to find that link from almost 2 days, but cannot find it. If anyone who that link please share.
In following assembly, I am trying to solve this call
__text:001C6E46 call _objc_msgSend
It should be great, if some one can help me understand the complete procedure.
__text:001C6DC0 ; -[NSWindow _windowMovedToRect:]
__text:001C6DC0 __NSWindow__windowMovedToRect__ proc near ; DATA XREF: __inst_meth:00993418o
__text:001C6DC0
__text:001C6DC0 var_C = dword ptr -0Ch
__text:001C6DC0 arg_0 = dword ptr 8
__text:001C6DC0 arg_8 = dword ptr 10h
__text:001C6DC0 arg_C = dword ptr 14h
__text:001C6DC0 arg_10 = dword ptr 18h
__text:001C6DC0 arg_14 = dword ptr 1Ch
__text:001C6DC0
__text:001C6DC0 push ebp
__text:001C6DC1 mov ebp, esp
__text:001C6DC3 push esi
__text:001C6DC4 push ebx
__text:001C6DC5 sub esp, 30h
__text:001C6DC8 call $+5
__text:001C6DCD pop ebx
__text:001C6DCE mov esi, [ebp+arg_0]
__text:001C6DD1 lea eax, [ebp+var_C]
__text:001C6DD4 mov [esp], eax
__text:001C6DD7 call _PSbuttondown
__text:001C6DDC mov edx, [ebp+var_C]
__text:001C6DDF test edx, edx
__text:001C6DE1 jz short loc_1C6E1D
__text:001C6DE3 mov eax, [esi+80h]
__text:001C6DE9 or dword ptr [eax+0B8h], 1000000h
__text:001C6DF3 mov eax, [ebp+arg_8]
__text:001C6DF6 mov edx, [ebp+arg_C]
__text:001C6DF9 mov [esp+8], eax
__text:001C6DFD mov [esp+0Ch], edx
__text:001C6E01 mov eax, [esi+8]
__text:001C6E04 mov edx, [esi+0Ch]
__text:001C6E07 mov [esp], eax
__text:001C6E0A mov [esp+4], edx
__text:001C6E0E call _NSEqualPoints
__text:001C6E13 test al, al
__text:001C6E15 jnz loc_1C6ED6
__text:001C6E1B jmp short loc_1C6E50
__text:001C6E1D ; ---------------------------------------------------------------------------
__text:001C6E1D
__text:001C6E1D loc_1C6E1D: ; CODE XREF: -[NSWindow _windowMovedToRect:]+21j
__text:001C6E1D mov eax, [ebp+arg_8]
__text:001C6E20 mov [esp+8], eax
__text:001C6E24 mov eax, [ebp+arg_C]
__text:001C6E27 mov [esp+0Ch], eax
__text:001C6E2B mov eax, [ebp+arg_10]
__text:001C6E2E mov [esp+10h], eax
__text:001C6E32 mov eax, [ebp+arg_14]
__text:001C6E35 mov [esp+14h], eax
__text:001C6E39 mov eax, ds:(off_926DC8 - 1C6DCDh)[ebx]
__text:001C6E3F mov [esp+4], eax
__text:001C6E43 mov [esp], esi
__text:001C6E46 call _objc_msgSend
__text:001C6E4B jmp loc_1C6ED6
__text:001C6E50 ; ---------------------------------------------------------------------------
__text:001C6E50
__text:001C6E50 loc_1C6E50: ; CODE XREF: -[NSWindow _windowMovedToRect:]+5Bj
__text:001C6E50 mov eax, [ebp+arg_8]
__text:001C6E53 mov [esp+8], eax
__text:001C6E57 mov eax, [ebp+arg_C]
__text:001C6E5A mov [esp+0Ch], eax
__text:001C6E5E mov eax, [ebp+arg_10]
__text:001C6E61 mov [esp+10h], eax
__text:001C6E65 mov eax, [ebp+arg_14]
__text:001C6E68 mov [esp+14h], eax
__text:001C6E6C mov eax, ds:(off_91D198 - 1C6DCDh)[ebx]
__text:001C6E72 mov [esp+4], eax
__text:001C6E76 mov [esp], esi
__text:001C6E79 call _objc_msgSend
__text:001C6E7E mov eax, ds:(off_91A4B8 - 1C6DCDh)[ebx]
__text:001C6E84 mov [esp+4], eax
__text:001C6E88 mov eax, ds:(off_928EE8 - 1C6DCDh)[ebx]
__text:001C6E8E mov [esp], eax
__text:001C6E91 call _objc_msgSend
__text:001C6E96 mov [esp+0Ch], esi
__text:001C6E9A mov edx, ds:(_NSWindowDidMoveNotification_ptr - 1C6DCDh)[ebx]
__text:001C6EA0 mov edx, [edx]
__text:001C6EA2 mov [esp+8], edx
__text:001C6EA6 mov edx, ds:(off_91B0DC - 1C6DCDh)[ebx]
__text:001C6EAC mov [esp+4], edx
__text:001C6EB0 mov [esp], eax
__text:001C6EB3 call _objc_msgSend
__text:001C6EB8 mov eax, ds:(_NSAccessibilityMovedNotification_ptr - 1C6DCDh)[ebx]
__text:001C6EBE mov eax, [eax]
__text:001C6EC0 mov [esp+8], eax
__text:001C6EC4 mov eax, ds:(off_91B030 - 1C6DCDh)[ebx]
__text:001C6ECA mov [esp+4], eax
__text:001C6ECE mov [esp], esi
__text:001C6ED1 call _objc_msgSend
__text:001C6ED6
__text:001C6ED6 loc_1C6ED6: ; CODE XREF: -[NSWindow _windowMovedToRect:]+55j
__text:001C6ED6 ; -[NSWindow _windowMovedToRect:]+8Bj
__text:001C6ED6 add esp, 30h
__text:001C6ED9 pop ebx
__text:001C6EDA pop esi
__text:001C6EDB leave
__text:001C6EDC retn
__text:001C6EDC __NSWindow__windowMovedToRect__ endp
This site mentions a tool called otx that appears to decode the selector for you.

MASM division for negative number

I'm trying divide two numbers in assembly[Irvine-Intel x86 processor].
Here is my code:
mov eax, 4
mov edx, 0
mov ebx, 2
div ebx
I get the correct answer for the division, but when i change the value to a negative number, it does not give me the correct answer.
mov eax, -4
mov edx, 0
mov ebx, 2
div ebx
As I know, the "div" is unsigned divide. So how if I want to do division with negative number?
You should use IDIV.
IDIV instruction is a divide operation. IDIV is for signed numbers wheareas DIV is for unsigned numbers.
mov eax, -4
xor edx, edx ; mov edx, 0
mov ebx, 2
div ebx