mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Use "jmps" macro instead of #define.
This commit is contained in:
parent
618d5ddaff
commit
badaeac81f
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
617
src/stub/src/arch/i386/macros.S
Normal file
617
src/stub/src/arch/i386/macros.S
Normal file
|
@ -0,0 +1,617 @@
|
|||
/*
|
||||
; macros.ash --
|
||||
;
|
||||
; This file is part of the UPX executable compressor.
|
||||
;
|
||||
; Copyright (C) 1996-2006 Markus Franz Xaver Johannes Oberhumer
|
||||
; Copyright (C) 1996-2006 Laszlo Molnar
|
||||
; All Rights Reserved.
|
||||
;
|
||||
; UPX and the UCL library are free software; you can redistribute them
|
||||
; and/or modify them under the terms of the GNU General Public License as
|
||||
; published by the Free Software Foundation; either version 2 of
|
||||
; the License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; see the file COPYING.
|
||||
; If not, write to the Free Software Foundation, Inc.,
|
||||
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
;
|
||||
; Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
; <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
;
|
||||
*/
|
||||
|
||||
.code32
|
||||
.intel_syntax noprefix
|
||||
|
||||
.macro section name
|
||||
.section \name
|
||||
.code32
|
||||
.endm
|
||||
|
||||
.macro CPU id
|
||||
.ifc \id, 386
|
||||
//.arch i386, nojumps
|
||||
.endif
|
||||
.ifc \id, 486
|
||||
.arch i486, nojumps
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro jmps target
|
||||
.byte 0xeb, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jos target
|
||||
.byte 0x70, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jnos target
|
||||
.byte 0x71, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jcs target
|
||||
.byte 0x72, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jncs target
|
||||
.byte 0x73, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jzs target
|
||||
.byte 0x74, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jnzs target
|
||||
.byte 0x75, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jnas target
|
||||
.byte 0x76, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jas target
|
||||
.byte 0x77, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jss target
|
||||
.byte 0x78, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jnss target
|
||||
.byte 0x79, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jps target
|
||||
.byte 0x7a, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jnps target
|
||||
.byte 0x7b, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jls target
|
||||
.byte 0x7c, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jnls target
|
||||
.byte 0x7d, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jngs target
|
||||
.byte 0x7e, \target - . - 1
|
||||
.endm
|
||||
|
||||
.macro jgs target
|
||||
.byte 0x7f, \target - . - 1
|
||||
.endm
|
||||
|
||||
#define jes jzs
|
||||
#define jnes jnzs
|
||||
#define jbes jnas
|
||||
|
||||
/*
|
||||
;; =============
|
||||
;; ============= 32-BIT CALLTRICK & JUMPTRICK
|
||||
;; =============
|
||||
|
||||
;; call & jump trick : 2 in 1
|
||||
*/
|
||||
|
||||
.macro cjt32 addvalue
|
||||
section CALLTR00
|
||||
mov ecx, offset filter_length
|
||||
calltrickloop:
|
||||
mov al, [edi]
|
||||
inc edi
|
||||
sub al, 0xE8
|
||||
ct1:
|
||||
cmp al, 1
|
||||
ja calltrickloop
|
||||
section CTCLEVE1
|
||||
cmpb [edi], offset filter_cto
|
||||
jnzs calltrickloop
|
||||
section CALLTR01
|
||||
mov eax, [edi]
|
||||
mov bl, [edi + 4]
|
||||
section CTBSHR01
|
||||
shr ax, 8
|
||||
section CTBROR01
|
||||
xchg ah, al
|
||||
section CTBSWA01
|
||||
rol eax, 16
|
||||
xchg ah, al
|
||||
section CALLTR02
|
||||
sub eax, edi
|
||||
sub bl, 0xE8
|
||||
|
||||
.ifnc \addvalue, 0
|
||||
add eax, \addvalue
|
||||
.endif
|
||||
|
||||
mov [edi], eax
|
||||
add edi, 5
|
||||
mov al, bl
|
||||
loop ct1
|
||||
|
||||
section CALLTR10
|
||||
//;; 32-bit call XOR jump trick
|
||||
mov ecx, offset filter_length
|
||||
ctloop1:
|
||||
section CALLTRE8
|
||||
mov al,0xE8
|
||||
section CALLTRE9
|
||||
mov al,0xE9
|
||||
section CALLTR11
|
||||
ctloop2:
|
||||
repnz
|
||||
scasb
|
||||
jnzs ctend
|
||||
section CTCLEVE2
|
||||
cmpb [edi], offset filter_cto
|
||||
jnzs ctloop2
|
||||
section CALLTR12
|
||||
mov eax, [edi]
|
||||
section CTBSHR11
|
||||
shr ax, 8
|
||||
section CTBROR11
|
||||
xchg ah, al
|
||||
section CTBSWA11
|
||||
rol eax, 16
|
||||
xchg ah, al
|
||||
section CALLTR13
|
||||
sub eax, edi
|
||||
|
||||
.ifnc \addvalue, 0
|
||||
add eax, \addvalue
|
||||
.endif
|
||||
|
||||
stosd
|
||||
jmps ctloop1
|
||||
ctend:
|
||||
.endm
|
||||
|
||||
/*
|
||||
;; call/jump/jcc trick; also used more than once (and/or optionally), so
|
||||
;; ecx has byte count (not count of applied instances), and
|
||||
;; edi points to buffer.
|
||||
*/
|
||||
.macro ckt32 addvalue, cto8
|
||||
// 1st param: effective addvalue (typically 0 or edi; any rvalue)
|
||||
// 2nd param: where is cto8 (dl, bl, or literal)
|
||||
|
||||
section CKLLTR00
|
||||
.ifnc \addvalue, 0
|
||||
mov esi, \addvalue
|
||||
.endif
|
||||
jmps ckstart
|
||||
ckloop3:
|
||||
mov al, [edi]
|
||||
add edi, 1
|
||||
section CKLLTR10 // Jcc only
|
||||
cmp al, 0x80 // lo of 6-byte Jcc
|
||||
jb ckloop2
|
||||
cmp al, 0x8f // hi of 6-byte Jcc
|
||||
ja ckloop2
|
||||
cmpb [edi -2], 0x0F // prefix of 6-byte Jcc
|
||||
jes ckmark
|
||||
ckloop2:
|
||||
section CKLLTR20
|
||||
sub al, 0xE8
|
||||
cmp al, 0xE9 - 0xE8
|
||||
jas ckcount
|
||||
ckmark:
|
||||
cmp [edi], \cto8
|
||||
jnzs ckcount
|
||||
mov eax, [edi]
|
||||
|
||||
shr ax, 8
|
||||
rol eax, 16
|
||||
xchg ah, al
|
||||
// above 3 instr are equivalent to the following 2 instr:
|
||||
// mov al, 0 ; clear cto8 [setup partial-write stall]
|
||||
// bswap eax ; not on 386: need 486 and up
|
||||
|
||||
sub eax, edi
|
||||
.ifnc \addvalue, 0
|
||||
add eax, esi
|
||||
.endif
|
||||
mov [edi], eax
|
||||
add edi, 4
|
||||
ckstart:
|
||||
sub ecx, 4
|
||||
section CKLLTR30 // Jcc only
|
||||
mov al, [edi]
|
||||
add edi, 1
|
||||
loop ckloop2 // prefix cannot overlap previous displacement
|
||||
section CKLLTR40
|
||||
ckcount:
|
||||
sub ecx, 1
|
||||
jgs ckloop3
|
||||
ckend:
|
||||
.endm
|
||||
|
||||
// =============
|
||||
// ============= 32-BIT RELOCATIONS
|
||||
// =============
|
||||
|
||||
.macro reloc32 buffer, destination, addvalue
|
||||
section RELOC320
|
||||
reloc_main:
|
||||
xor eax, eax
|
||||
mov al, [\buffer]
|
||||
inc \buffer
|
||||
or eax, eax
|
||||
jzs reloc_endx
|
||||
cmp al, 0xEF
|
||||
ja reloc_fx
|
||||
reloc_add:
|
||||
add \destination, eax
|
||||
#if 1
|
||||
mov eax, [\destination]
|
||||
xchg ah, al
|
||||
rol eax, 16
|
||||
xchg ah, al
|
||||
add eax, \addvalue
|
||||
mov [\destination], eax
|
||||
#else
|
||||
add [\destination], \addvalue
|
||||
#endif
|
||||
jmps reloc_main
|
||||
reloc_fx:
|
||||
and al, 0x0F
|
||||
shl eax, 16
|
||||
mov ax, [\buffer]
|
||||
add \buffer, 2
|
||||
section REL32BIG
|
||||
or eax, eax
|
||||
jnzs reloc_add
|
||||
mov eax, [\buffer]
|
||||
add \buffer, 4
|
||||
section RELOC32J
|
||||
jmps reloc_add
|
||||
reloc_endx:
|
||||
section REL32END
|
||||
.endm
|
||||
|
||||
/*
|
||||
;; =============
|
||||
;; ============= 32-BIT CALL TRICK UNFILTER WITH MostRecentlyUsed BUFFER
|
||||
;; =============
|
||||
|
||||
;;;; names of pseudo-sections for addLoader:
|
||||
;; LXUNFnnn Linux unfilter
|
||||
;; LXMRUnnn MostRecentlyUsed recoding of destinations
|
||||
;; MRUARBnn arbitrary number of entries in wheel
|
||||
;; MRUBITSn power of 2 entries in wheel (smaller code)
|
||||
;; MRUBYTEn 256 entries in wheel (smallest code)
|
||||
*/
|
||||
|
||||
/*
|
||||
;; I got confused by the syntactic sugar of the fake %ifdefs.
|
||||
;; I can read the section name more easily when it is at the left margin.
|
||||
;; Also, some of the logic to select the sections is not that simple,
|
||||
;; and any mismatch between the logic and the %ifdefs is very confusing.
|
||||
;; Instead, I use comments after the section name, and blank lines for grouping.
|
||||
*/
|
||||
|
||||
.macro ctojr32
|
||||
|
||||
section LXUNF000 // enter at +0 for decompression; +2 for unfiltering
|
||||
jmps decompr0
|
||||
section LXUNF002
|
||||
// 2+ address of decompress subroutine
|
||||
// unfilter(upx_byte *, length, cto8)
|
||||
lxunfilter:
|
||||
pop edx // return address
|
||||
pop eax // upx_byte *, same as addvalue
|
||||
pop ecx // length
|
||||
xchg eax, edi // edi= pointer; eax= saved_edi
|
||||
pusha // save C-convention ebx, ebp, esi, edi; also eax, edx
|
||||
|
||||
// at most one of the next 2
|
||||
section MRUBYTE0 // 256==n_mru
|
||||
xor ebx, ebx // zero
|
||||
section LXMRU005 // 0!=n_mru
|
||||
mov ebx, offset NMRU // modified N_MRU or N_MRU -1
|
||||
|
||||
section LXMRU006 // 0!=n_mru
|
||||
push 0x0f // prefix of 6-byte Jcc <d32>
|
||||
pop eax
|
||||
mov ah, [esp + 8*4] // cto8
|
||||
section LXMRU007 // 0==n_mru
|
||||
push 0x0f // prefix of 6-byte Jcc <d32>
|
||||
pop ebx
|
||||
mov bh, [esp + 8*4] // cto8
|
||||
|
||||
section LXUNF008
|
||||
mov dl, [esp + 8*4] // cto8
|
||||
|
||||
section LXUNF010
|
||||
jmp lxunf0
|
||||
decompr0:
|
||||
|
||||
// These #define are only if 0!=n_mru;
|
||||
// else 0x0F==bl && cto8==bh==dh && 0xE8==dl && addvalue==esi .
|
||||
#define __n_mru [esi]
|
||||
#define __n_mru1 [esi]
|
||||
#define __tail [esi + 4*1]
|
||||
#define __cto8_e8e9 [esi + 4*2]
|
||||
#define __cto8_0f [esi + 4*3]
|
||||
#define __addvalue [esi + 4*4]
|
||||
#define __tmp ebp
|
||||
#define __hand ebx
|
||||
#define __hand_l bl
|
||||
#define __kh edx
|
||||
#define __kh_l dl
|
||||
|
||||
section LXJCC010
|
||||
lxunf2: // have seen 0x80..0x8f of possible recoded 6-byte Jcc <d32>
|
||||
movzxw ebp, [edi] // 2 bytes, zero-extended
|
||||
|
||||
section LXMRU045 // 0!=n_mru
|
||||
sub ebp, __cto8_0f
|
||||
section LXMRU046 // 0==n_mru
|
||||
sub ebp, ebx
|
||||
|
||||
section LXJCC020 // 0==n_mru, or Jcc excluded ('sub' of equals clears Carry)
|
||||
jne unfcount
|
||||
section LXJCC021 // 0!=n_mru and Jcc participates// must set Carry
|
||||
sub ebp, 1 // set Carry iff in range
|
||||
jnb unfcount
|
||||
|
||||
section LXJCC023 // found Jcc// re-swap 0x8Y opcode and 0x0f prefix
|
||||
mov [edi -1], bl // 0x0f prefix
|
||||
dec ecx // preserve Carry
|
||||
mov [edi], al // Jcc opcode
|
||||
inc edi // preserve Carry
|
||||
|
||||
section LXUNF037
|
||||
#define __jc eax
|
||||
|
||||
lxunf: // in: Carry set iff we should apply mru and 0!=n_mru
|
||||
mov eax, [edi] // BE32 displacement with cto8 in low 8 bits
|
||||
|
||||
section LXUNF386 // 0!=n_mru && 386
|
||||
pushf
|
||||
section LXUNF387 // ==386
|
||||
shr ax, 8
|
||||
rol eax, 16
|
||||
xchg ah, al
|
||||
section LXUNF388 // 0!=n_mru && 386
|
||||
popf
|
||||
jncs unf_store // do not apply mru
|
||||
|
||||
section LXUNF486 // >=486
|
||||
mov al, 0
|
||||
CPU 486
|
||||
bswap eax // preserve Carry (2-byte instruction)
|
||||
CPU 386
|
||||
section LXUNF487 // 0!=n_mru && >=486
|
||||
jncs unf_store // do not apply mru
|
||||
|
||||
section LXMRU065 // 0!=n_mru
|
||||
shr __jc, 1 // eax= jc, or mru index
|
||||
jnc mru4 // not 1st time for this jc
|
||||
section MRUBYTE3
|
||||
dec __hand_l
|
||||
section MRUARB30
|
||||
dec __hand
|
||||
section MRUBITS3
|
||||
and __hand, __n_mru1
|
||||
section MRUARB40
|
||||
jge mru3
|
||||
add __hand, __n_mru
|
||||
mru3:
|
||||
section LXMRU070
|
||||
|
||||
mov [esp + 4*__hand], __jc // 1st time: mru[hand] = jc
|
||||
jmps unf_store
|
||||
|
||||
mru4: // not 1st time for this jc
|
||||
lea __kh, [__jc + __hand] // kh = jc + hand
|
||||
section MRUBYTE4
|
||||
movzx __kh, __kh_l
|
||||
section MRUBITS4
|
||||
and __kh, __n_mru1
|
||||
section MRUARB50
|
||||
cmp __kh, __n_mru
|
||||
jb mru5
|
||||
sub __kh, __n_mru
|
||||
mru5:
|
||||
section LXMRU080
|
||||
mov __jc, [esp + 4*__kh] // jc = mru[kh]
|
||||
section MRUBYTE5
|
||||
dec __hand_l
|
||||
section MRUARB60
|
||||
dec __hand
|
||||
section MRUBITS5
|
||||
and __hand, __n_mru1
|
||||
section MRUARB70
|
||||
jge mru6
|
||||
add __hand, __n_mru
|
||||
mru6:
|
||||
section LXMRU090
|
||||
|
||||
mov __tmp, [esp + 4*__hand] // tmp = mru[hand]
|
||||
test __tmp,__tmp
|
||||
jnzs mru8
|
||||
|
||||
push __jc // ran out of registers
|
||||
mov eax, __tail
|
||||
|
||||
section MRUBYTE6
|
||||
dec al
|
||||
section MRUARB80
|
||||
dec eax
|
||||
section MRUBITS6
|
||||
and eax, __n_mru1
|
||||
section MRUARB90
|
||||
jge mru7
|
||||
add eax, __n_mru
|
||||
mru7:
|
||||
section LXMRU100
|
||||
|
||||
xor __tmp,__tmp
|
||||
mov __tail, eax
|
||||
xchg [4+ esp + 4*eax], __tmp // tmp = mru[tail]; mru[tail] = 0
|
||||
pop __jc
|
||||
mru8:
|
||||
mov [esp + 4*__kh ], __tmp // mru[kh] = tmp
|
||||
mov [esp + 4*__hand], __jc // mru[hand] = jc
|
||||
section LXUNF040
|
||||
unf_store:
|
||||
sub eax, edi
|
||||
sub ecx, 4
|
||||
|
||||
// one of the next2
|
||||
section LXMRU110 // 0!=n_mru
|
||||
add eax, __addvalue
|
||||
section LXMRU111 // 0==n_mru
|
||||
add eax, esi // addvalue (same as initial pointer)
|
||||
|
||||
section LXUNF041
|
||||
mov [edi], eax
|
||||
add edi, 4
|
||||
jmps unfcount
|
||||
section LXUNF042
|
||||
lxunf0: // continuation of entry prolog for unfilter
|
||||
section LEXEC016 // bug in APP: jmp and label must be in same .asx/.asy
|
||||
jmp lxunf0 // this instr does not really go here!
|
||||
|
||||
section LXMRU010 // 0!=n_mru
|
||||
push eax // cto8_0f
|
||||
section LXJMPA00 // only JMP, and not CALL, is filtered
|
||||
mov al, 0xE9
|
||||
section LXCALLB0 // only CALL, or both CALL and JMP are filtered
|
||||
mov al, 0xE8
|
||||
section LXUNF021 // common tail
|
||||
push eax // cto8_e8e9
|
||||
push 0 // tail
|
||||
push ebx // n_mru or n_mru1
|
||||
mov esi, esp // flat model "[esi]" saves a byte over "[ebp]"
|
||||
|
||||
section LXMRU022 // 0==n_mru
|
||||
pop esi // addvalue
|
||||
mov edx, ebx // dh= cto8
|
||||
section LXJMPA01 // only JMP, and not CALL, is filtered
|
||||
mov dl, 0xE9
|
||||
section LXCALLB1 // only CALL, or both CALL and JMP are filtered
|
||||
mov dl, 0xE8
|
||||
|
||||
|
||||
section MRUBITS1
|
||||
inc __hand // n_mru1 ==> n_mru
|
||||
section LXMRU030
|
||||
lxunf1: // allocate and clear mru[]
|
||||
push 0
|
||||
|
||||
// one of the next 2, if n_mru
|
||||
section MRUBYTE1
|
||||
dec __hand_l
|
||||
section MRUARB10
|
||||
dec __hand
|
||||
|
||||
section LXMRU040 // 0!=n_mru
|
||||
jnzs lxunf1 // leaves 0=='hand'
|
||||
|
||||
section LXUNF030
|
||||
lxctloop:
|
||||
movzxw eax, [edi] // 2 bytes, zero extended
|
||||
add edi, 1
|
||||
section LXJCC000
|
||||
cmp al, 0x80 // lo of Jcc <d32>
|
||||
jb lxct1
|
||||
cmp al, 0x8f // hi of Jcc <d32>
|
||||
jbes lxunf2
|
||||
lxct1:
|
||||
|
||||
section LXCJ0MRU // 0==n_mru
|
||||
sub eax, edx
|
||||
section LXCJ1MRU // 0!=n_mru
|
||||
sub eax, __cto8_e8e9
|
||||
|
||||
// both CALL and JMP are filtered
|
||||
section LXCALJMP
|
||||
sub eax, 1+ (0xE9 - 0xE8) // set Carry iff in range (result: -2, -1)
|
||||
|
||||
// only CALL, or only JMP, is filtered
|
||||
section LXCALL00 // 0==n_mru
|
||||
je lxunf
|
||||
section LXCALL01 // 0!=n_rmu
|
||||
sub eax, 1 // set Carry iff in range
|
||||
|
||||
section LXCJ2MRU // 0==n_mru, or apply mru to all that are filtered here
|
||||
jb lxunf // only Carry (Borrow) matters
|
||||
section LXCJ4MRU // 0!=n_mru, but apply mru only to subset of filtered here
|
||||
jnb unfcount // was not filtered anyway: do not unfilter
|
||||
|
||||
//we will unfilter, and 0!=n_mru, but should we apply mru?
|
||||
section LXCJ6MRU // apply mru to JMP only (0xFF==al)
|
||||
jpe lxct3 // jump if even number of 1 bits in al
|
||||
section LXCJ7MRU // apply mru to CALL only (0xFE==al)
|
||||
jpo lxct3 // jump if odd number of 1 bits in al
|
||||
section LXCJ8MRU // do not apply mru to one or both
|
||||
clc
|
||||
lxct3:
|
||||
jmps lxunf
|
||||
|
||||
section LXUNF034
|
||||
unfcount:
|
||||
sub ecx, 1
|
||||
jgs lxctloop
|
||||
|
||||
section LXMRU055
|
||||
mov edi, esp // clear mru[] portion of stack
|
||||
section MRUBYTE2
|
||||
mov ecx, 4+ 256 // unused, tail, cto8_e8e9, cto8_0f
|
||||
section MRUBITS2
|
||||
mov ecx, __n_mru1
|
||||
add ecx, 1+ 4 // n_mru1, tail, cto8_e8e9, cto8_0f
|
||||
section MRUARB20
|
||||
mov ecx, __n_mru
|
||||
add ecx, 4 // n_mru, tail, cto8_e8e9, cto8_0f
|
||||
section LXMRU057
|
||||
xor eax, eax
|
||||
rep
|
||||
stosd
|
||||
mov esp, edi
|
||||
|
||||
section LXMRU058 // 0==n_mru
|
||||
push esi
|
||||
section LXUNF035
|
||||
popa
|
||||
xchg eax, edi
|
||||
push ecx
|
||||
push eax
|
||||
push edx
|
||||
ret
|
||||
.endm
|
||||
|
||||
// vi:ts=8:et:nowrap
|
|
@ -30,12 +30,10 @@
|
|||
; <jreiser@users.sourceforge.net>
|
||||
;
|
||||
*/
|
||||
|
||||
#include "arch/i386/macros.S"
|
||||
// CPU 386
|
||||
|
||||
// CPU 386
|
||||
|
||||
#define jmps jmp short
|
||||
#define jmpn jmp near
|
||||
|
||||
/*************************************************************************
|
||||
// program entry point
|
||||
|
|
|
@ -30,12 +30,10 @@
|
|||
; <jreiser@users.sourceforge.net>
|
||||
;
|
||||
*/
|
||||
|
||||
#include "arch/i386/macros.S"
|
||||
// CPU 386
|
||||
|
||||
// CPU 386
|
||||
|
||||
#define jmps jmp short
|
||||
#define jmpn jmp near
|
||||
|
||||
/*************************************************************************
|
||||
// program entry point
|
||||
|
|
Loading…
Reference in New Issue
Block a user