<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Выход из рутины до ближайшего цикла]]></title><description><![CDATA[<p dir="auto">собенности</p>
<ol>
<li>переход на следующий адрес по инструкциям ветвления вычисляется Lua кодом по ret, jmp, jmp condition до исполнения кода</li>
<li>определение опкодов ветвления по readmem без дизассемблериования</li>
<li>по тестам последний брейкпоинт снимается на ближайшем цикле</li>
</ol>
<p dir="auto">Пример лога до близжайшего цикла, когда поднимается из рутины вверх</p>
<pre><code>&gt; RET    :00454684 - C3 - ret  
&gt; --&gt;&gt;    :0045468C - 5B - pop ebx
&gt; RET    :0045468F - C3 - ret  
&gt; --&gt;&gt;    :00454695 - C3 - ret  
&gt; RET    :00454695 - C3 - ret  
&gt; --&gt;&gt;    :00437F36 - 5B - pop ebx
&gt; RET    :00437F37 - C3 - ret  
&gt; --&gt;&gt;    :004272EB - 5B - pop ebx
&gt; RET    :004272EC - C3 - ret  
&gt; --&gt;&gt;    :004273E9 - 5E - pop esi
&gt; RET    :004273EA - C3 - ret  
&gt; --&gt;&gt;    :00437A2E - 5F - pop edi
&gt; RET    :00437A34 - C3 - ret  
&gt; --&gt;&gt;    :0043B749 - 5B - pop ebx
&gt; RET    :0043B74D - C3 - ret  
&gt; --&gt;&gt;    :00427195 - 5F - pop edi
&gt; RET    :00427198 - C3 - ret  
&gt; --&gt;&gt;    :004376BB - 8B 45 FC  - mov eax,[ebp-04]
&gt; RET    :004376C2 - C2 0400 - ret 0004
&gt; --&gt;&gt;    :0043B880 - 89 46 0C  - mov [esi+0C],eax
&gt; RET    :0043B88A - C3 - ret  
&gt; --&gt;&gt;    :0043BFF4 - 84 C0  - test al,al
&gt; isCJMP    :0043BFF6 - 75 09 - jne 0043C001
&gt; RET    :0043C003 - C3 - ret  
&gt; --&gt;&gt;    :0044DFAD - 5E - pop esi
&gt; RET    :0044DFAF - C3 - ret  
&gt; --&gt;&gt;    :00437A2E - 5F - pop edi 
</code></pre>
<pre><code>\--&lsqb;&lsqb;
	Версия: 0.01.b1
	Выход из рутины до близжайшего цикла
&rsqb;&rsqb;--

mainAddress = 0x0045B5A4 -- адрес некоторого параметра в игре
nextAddress = nil
is64bits = targetIs64Bit()

tableInstruction ={}
tableBreakpointsAddress ={}


function ContaintsBeakPoint(address)
	for i = 1, #tableBreakpointsAddress do
		if tableBreakpointsAddress[i] == address then
			return true
		end
	end
	return false
end

\-- Возвращает адрес по ret
function GetNextAddressFromRET(address)
	if is64bits then
		nextAddress = readPointer(RSP)
	else
		nextAddress = readPointer(ESP)
	end
	return nextAddress
end
\-- Возвращает адрес по Jmp
function GetNextAddressFromJMP(address)
	local disassembledstring = nil
	if is64bits then
		local disassembledstring = disassemble(RIP)
	else
		local disassembledstring = disassemble(EIP)
	end
	local _, opcode, _, _ = splitDisassembledString(disassembledstring)
	return GetAddressFromOpcode(opcode)
end


function ToBits(num, bits)
	local t = {}
	for b = bits, 1, -1 do
		rest = math.fmod(num,2)
		t[b] = math.floor(rest)
		num = (num-rest)/2
	end
	
	if num == 0 then
		return t
	else
		return {'Not enough bits to represent this number'}
	end
end


function GetEFLAGS()
	local bitsTable = ToBits(EFLAGS, 16)

	local tableEFLAGS =
	{
		OF = bitsTable[17-12],
		DF = bitsTable[17-11],
		SF = bitsTable[17-8],
		ZF = bitsTable[17-7],
		AF = bitsTable[17-5],
		PF = bitsTable[17-3],
		CF = bitsTable[17-1]
	}
	
	--for k,v in pairs(tableEFLAGS) do
	--	print (k..' = '..v)
	--end
	--
	--print(EFLAGS)
	--local s = ''
	--for i=1,#bitsTable do
	--	s = s..bitsTable[i]
	--end
	--print(s)		
	return tableEFLAGS	
end

\-- Возвращает адрес из опкода jmp dword ptr [edi*4+07895D88] или jmp 07895D88
\--print(string.format('%08X', newAddress))
function GetAddressFromOpcode (opcode)

	local rightLine = string.match(opcode, '%S*%s*(%S*)')
	local isPointer = string.match(opcode, '%[')
	if isPointer then
		rightLine = string.match(opcode, '%[(.*)%]')
		--00454664 - 8B 83 60030000        - mov eax,[ebx+00000360]
		if string.match(opcode, 'eax') then rightLine = string.gsub(rightLine, 'eax', EAX) end
		if string.match(opcode, 'ebx') then rightLine = string.gsub(rightLine, 'ebx', EBX) end
		if string.match(opcode, 'ecx') then rightLine = string.gsub(rightLine, 'ecx', ECX) end
		if string.match(opcode, 'edx') then rightLine = string.gsub(rightLine, 'edx', EDX) end
		if string.match(opcode, 'esi') then rightLine = string.gsub(rightLine, 'esi', ESI) end
		if string.match(opcode, 'edi') then rightLine = string.gsub(rightLine, 'edi', EDI) end
		if string.match(opcode, 'esp') then rightLine = string.gsub(rightLine, 'esp', ESP) end
		if string.match(opcode, 'ebp') then rightLine = string.gsub(rightLine, 'ebp', EBP) end
		
		if is64bits then
			if string.match(opcode, 'rax') then rightLine = string.gsub(rightLine, 'rax', RAX) end
			if string.match(opcode, 'rbx') then rightLine = string.gsub(rightLine, 'rbx', RBX) end
			if string.match(opcode, 'rcx') then rightLine = string.gsub(rightLine, 'rcx', RCX) end
			if string.match(opcode, 'rdx') then rightLine = string.gsub(rightLine, 'rdx', RDX) end
			if string.match(opcode, 'rsi') then rightLine = string.gsub(rightLine, 'rsi', RSI) end
			if string.match(opcode, 'rdi') then rightLine = string.gsub(rightLine, 'rdi', RDI) end
			if string.match(opcode, 'rsp') then rightLine = string.gsub(rightLine, 'rsp', RSP) end
			if string.match(opcode, 'rbp') then rightLine = string.gsub(rightLine, 'rbp', RBP) end
			
			if string.match(opcode, 'r8') then rightLine = string.gsub(rightLine, 'r8', R8) end
			if string.match(opcode, 'r9') then rightLine = string.gsub(rightLine, 'r9', R9) end
			if string.match(opcode, 'r10') then rightLine = string.gsub(rightLine, 'r10', R10) end
			if string.match(opcode, 'r11') then rightLine = string.gsub(rightLine, 'r11', R11) end
			if string.match(opcode, 'r12') then rightLine = string.gsub(rightLine, 'r12', R12) end
			if string.match(opcode, 'r13') then rightLine = string.gsub(rightLine, 'r13', R13) end
			if string.match(opcode, 'r14') then rightLine = string.gsub(rightLine, 'r14', R14) end
			if string.match(opcode, 'r15') then rightLine = string.gsub(rightLine, 'r15', R15) end
		end
		
		return getAddress('%['..rightLine..'%]')
	end
	
	return getAddress(rightLine)
end

\-- Возвращает адрес по Jmp condition, когда тот выполняется или не выполняется
function GetNextAddressFromConditionJMP(address, size)

	local _,opcode,_,_ = splitDisassembledString(disassemble(address))
	local leftString = string.match(opcode, '%S*')
	local eflags = GetEFLAGS()
	
	if (leftString == 'jnz' or leftString == 'jne') 										then	if eflags.ZF == 0 											then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'je' or leftString == 'jz') 								then if eflags.ZF == 1 											then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jg' or leftString == 'jnle')								then if eflags.ZF == 0 and eflags.SF == eflags.OF 	then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jb' or leftString == 'jc' or leftString == 'jnae') 	then if eflags.CF == 1 											then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jae')															then	if eflags.CF == 0											then return GetAddressFromOpcode(opcode) end 
		elseif (leftString == 'ja') 															then if eflags.CF == 0 and eflags.ZF == 0 				then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jbe') 															then if eflags.CF == 1 and eflags.ZF == 1 				then return GetAddressFromOpcode(opcode) end	
		elseif (leftString == 'jl' or leftString == 'jnge') 								then if eflags.SF ~= eflags.OF 								then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jle' or leftString == 'jng') 								then if eflags.ZF == 1 or eflags.SF ~= eflags.OF 		then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jna') 															then if eflags.CF == 1 or eflags.ZF == 1 					then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jc') 															then if eflags.CF == 1 											then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jp' or leftString == 'jpe') 								then	if eflags.PF == 1											then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jnp' or leftString == 'jpo') 								then if eflags.PF == 0 											then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jnb' or leftString == 'jnc') 								then if eflags.CF == 0 											then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jnbe') 														then if eflags.CF == 0 and eflags.ZF == 0 				then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jno') 															then	if eflags.OF == 0 											then return GetAddressFromOpcode(opcode) end	
		elseif (leftString == 'jns') 															then	if eflags.SF == 0 											then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jo') 															then if eflags.OF == 1 											then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'js') 															then if eflags.SF == 1 											then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jge' or leftString == 'jnl') 								then if eflags.CF == 1 and eflags.OF == 1 				then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jrcxz') 														then if RCX == 0 												then return GetAddressFromOpcode(opcode) end
		elseif (leftString == 'jecxz') 														then if ECX == 0 												then return GetAddressFromOpcode(opcode) end
	end
	return address + size
end

function IsRet(address)
   local value = readBytes(address,1, false)
   return value == 0xC3 or value == 0xCB or  value == 0xC2 or value == 0xCA
end

function IsCall(address)
   local value = readBytes(address,1, false)
   return value == 0xFF or value == 0xE8 -- or  value == 0x9A
end

function IsJMP(address)
	local value = readBytes (address, 1, false)
	if value == 0xFF then
		if readBytes (address + 1, 1, false) == 05 then
			return false
		end
	end
	return value == 0xEB or value == 0xE9 or  value == 0xFF -- or value == 0xEA
\--&lsqb;&lsqb;
	078921A8 - EB 38                 		- jmp 078921E2
	0789242D - E9 E2000000     			- jmp 07892514
	07894F4C - FF E2                 			- jmp edx
	07895C67 - FF 24 BD 885D8907     - jmp dword ptr [edi*4+07895D88]
&rsqb;&rsqb;--	
end




function IsConditionJMP(address)
	local value = readBytes (address, 1, false)
	return  
		value == 0x77 or value == 0x73 or value == 0x72 or value == 0x76 or
		value == 0xE3 or value == 0x74 or value == 0x7F or value == 0x7D or
		value == 0x7C or value == 0x7E or value == 0x75 or value == 0x71 or
		value == 0x7B or value == 0x79 or value == 0x70 or value == 0x7A or
		value == 0x78 or value == 0x0F
end

\-- Возвращает адрес, на который, будет прыжок
function GetNextAddress(addressXIP)
	-- Определить на какой инструкции мы находимся, чтобы узнать на какую следующу инструкцию ставить бряк
	-- ret				- прыжок по смещению ESP/RSP
	-- jmp				- прыжок без условия
	-- je, jne, jxx	- прыжок с улосвием
	
	-- Определить размер инструкции, тип инструкции на текущем addressXIP
	local findIndex = -1
	for i = 1, #tableInstruction do
		if tableInstruction[i].XIP == addressXIP then
			findIndex = i
			break
		end
	end
	
	local size = 0
	local isRet = false
	local isJMP = false
	local isCJMP = false
		
	if findIndex ==  -1 then
		-- Если нет данных
		---------------- ЗАПОМИНАТЬ РАЗМЕР ИНСТРУКЦИИ (чтобы не дизассемблировать повторно)
		size = getInstructionSize(addressXIP)
		isRet = IsRet(addressXIP)
		isJMP = IsJMP(addressXIP)
		isCJMP = IsConditionJMP(addressXIP)
		table.insert(tableInstruction, {XIP = addressXIP, SIZE = size, ISRET = isRet, ISJMP = isJMP,  ISCJMP = isCJMP})
	else
		-- Если данные есть
		size = tableInstruction[findIndex].SIZE
		isRet = tableInstruction[findIndex].ISRET
		isJMP = tableInstruction[findIndex].ISJMP
		isCJMP = tableInstruction[findIndex].ISCJMP
	end	
	---------------
	
	if isRet then
		print('&gt; RET	:' ..disassemble(nextAddress))
		nextAddress = GetNextAddressFromRET(addressXIP)
		print('&gt; --&gt;&gt;	:' ..disassemble(nextAddress))
	elseif isJMP then
		print('&gt; isJMP	:' ..disassemble(nextAddress))
		nextAddress =  GetNextAddressFromJMP(addressXIP)
	elseif isCJMP then
		print('&gt; isCJMP	:' ..disassemble(nextAddress))
		nextAddress = GetNextAddressFromConditionJMP(addressXIP, size)
	else
		nextAddress = addressXIP + size
	end
	
	return nextAddress
end


function debugger_onBreakpoint()

	local isContaintsBreakPoint = false
	
	-- Удалить прошлый брейкпоинт
	if(nextAddress ~= nil) then
		 isContaintsBreakPoint = ContaintsBeakPoint(nextAddress)
		 if isContaintsBreakPoint then
			debug_removeBreakpoint(nextAddress)
		end
	end	
	
	-- Поставить брейкпоинт на следующую инструкцию не входя в call-ы
	local XIP = 0
	if is64bits then XIP = EIP	else	XIP = RIP end
	
	nextAddress = GetNextAddress(XIP)
	if not ContaintsBeakPoint(nextAddress) then
		debug_setBreakpoint(nextAddress, 1, bptExecute, bpmDebugRegister)
		table.insert(tableBreakpointsAddress, nextAddress)
	end
	
	return 1 --1 не показывать дизассемблер
end

if getOpenedProcessID() == 0 then
  openProcess('test.exe')
end


\--bptWrite
\--bptAccess
debug_removeBreakpoint()
debug_setBreakpoint(mainAddress, 4, bptWrite, bpmDebugRegister)
</code></pre>
<p dir="auto">Справка</p>
<pre><code>77 cb JA rel8 D Valid Valid Jump short if above (CF=0 and ZF=0).
73 cb JAE rel8 D Valid Valid Jump short if above or equal (CF=0).
72 cb JB rel8 D Valid Valid Jump short if below (CF=1).
76 cb JBE rel8 D Valid Valid Jump short if below or equal (CF=1 or ZF=1).
72 cb JC rel8 D Valid Valid Jump short if carry (CF=1).
E3 cb JCXZ rel8 D N.E. Valid Jump short if CX register is 0.
E3 cb JECXZ rel8 D Valid Valid Jump short if ECX register is 0.
E3 cb JRCXZ rel8 D Valid N.E. Jump short if RCX register is 0.
74 cb JE rel8 D Valid Valid Jump short if equal (ZF=1).
7F cb JG rel8 D Valid Valid Jump short if greater (ZF=0 and SF=OF).
7D cb JGE rel8 D Valid Valid Jump short if greater or equal (SF=OF).
7C cb JL rel8 D Valid Valid Jump short if less (SF≠ OF).
7E cb JLE rel8 D Valid Valid Jump short if less or equal (ZF=1 or SF≠ OF).
76 cb JNA rel8 D Valid Valid Jump short if not above (CF=1 or ZF=1).
72 cb JNAE rel8 D Valid Valid Jump short if not above or equal (CF=1).
73 cb JNB rel8 D Valid Valid Jump short if not below (CF=0).
77 cb JNBE rel8 D Valid Valid Jump short if not below or equal (CF=0 andZF=0).
73 cb JNC rel8 D Valid Valid Jump short if not carry (CF=0).
75 cb JNE rel8 D Valid Valid Jump short if not equal (ZF=0).
7E cb JNG rel8 D Valid Valid Jump short if not greater (ZF=1 or SF≠ OF).
7C cb JNGE rel8 D Valid Valid Jump short if not greater or equal (SF≠ OF).
7D cb JNL rel8 D Valid Valid Jump short if not less (SF=OF).
7F cb JNLE rel8 D Valid Valid Jump short if not less or equal (ZF=0 and SF=OF).
71 cb JNO rel8 D Valid Valid Jump short if not overflow (OF=0).
7B cb JNP rel8 D Valid Valid Jump short if not parity (PF=0).
79 cb JNS rel8 D Valid Valid Jump short if not sign (SF=0).
75 cb JNZ rel8 D Valid Valid Jump short if not zero (ZF=0).
70 cb JO rel8 D Valid Valid Jump short if overflow (OF=1).
7A cb JP rel8 D Valid Valid Jump short if parity (PF=1).
7A cb JPE rel8 D Valid Valid Jump short if parity even (PF=1).
7B cb JPO rel8 D Valid Valid Jump short if parity odd (PF=0).
78 cb JS rel8 D Valid Valid Jump short if sign (SF=1).
74 cb JZ rel8 D Valid Valid Jump short if zero (ZF = 1).
0F 87 cw JA rel16 D N.S. Valid Jump near if above (CF=0 and ZF=0). Not supported in 64-bit mode.
0F 87 cd JA rel32 D Valid Valid Jump near if above (CF=0 and ZF=0).
0F 83 cw JAE rel16 D N.S. Valid Jump near if above or equal (CF=0). Not supported in 64-bit mode.
0F 83 cd JAE rel32 D Valid Valid Jump near if above or equal (CF=0).
0F 82 cw JB rel16 D N.S. Valid Jump near if below (CF=1). Not supported in 64-bit mode.
0F 82 cd JB rel32 D Valid Valid Jump near if below (CF=1).
0F 86 cw JBE rel16 D N.S. Valid Jump near if below or equal (CF=1 or ZF=1). Not supported in 64-bit mode.
0F 86 cd JBE rel32 D Valid Valid Jump near if below or equal (CF=1 or ZF=1).
0F 82 cw JC rel16 D N.S. Valid Jump near if carry (CF=1). Not supported in 64-bit mode.
0F 82 cd JC rel32 D Valid Valid Jump near if carry (CF=1).
0F 84 cw JE rel16 D N.S. Valid Jump near if equal (ZF=1). Not supported in 64-bit mode.
0F 84 cd JE rel32 D Valid Valid Jump near if equal (ZF=1).
0F 84 cw JZ rel16 D N.S. Valid Jump near if 0 (ZF=1). Not supported in 64-bit mode.
0F 84 cd JZ rel32 D Valid Valid Jump near if 0 (ZF=1).
0F 8F cw JG rel16 D N.S. Valid Jump near if greater (ZF=0 and SF=OF). Notsupported in 64-bit mode.
0F 8F cd JG rel32 D Valid Valid Jump near if greater (ZF=0 and SF=OF).
0F 8D cw JGE rel16 D N.S. Valid Jump near if greater or equal (SF=OF). Not supported in 64-bit mode.
0F 8D cd JGE rel32 D Valid Valid Jump near if greater or equal (SF=OF).
0F 8C cw JL rel16 D N.S. Valid Jump near if less (SF≠ OF). Not supported in 64-bit mode.
0F 8C cd JL rel32 D Valid Valid Jump near if less (SF≠ OF).
0F 8E cw JLE rel16 D N.S. Valid Jump near if less or equal (ZF=1 or SF≠ OF). Not supported in 64-bit mode.
0F 8E cd JLE rel32 D Valid Valid Jump near if less or equal (ZF=1 or SF≠ OF). 
0F 86 cw JNA rel16 D N.S. Valid Jump near if not above (CF=1 or ZF=1). Not supported in 64-bit mode.
0F 86 cd JNA rel32 D Valid Valid Jump near if not above (CF=1 or ZF=1).
0F 82 cw JNAE rel16 D N.S. Valid Jump near if not above or equal (CF=1). Not supported in 64-bit mode.
0F 82 cd JNAE rel32 D Valid Valid Jump near if not above or equal (CF=1).
0F 83 cw JNB rel16 D N.S. Valid Jump near if not below (CF=0). Not supported in 64-bit mode.
0F 83 cd JNB rel32 D Valid Valid Jump near if not below (CF=0).
0F 87 cw JNBE rel16 D N.S. Valid Jump near if not below or equal (CF=0 and ZF=0). Not supported in 64-bit mode.
0F 87 cd JNBE rel32 D Valid Valid Jump near if not below or equal (CF=0 and ZF=0).
0F 83 cw JNC rel16 D N.S. Valid Jump near if not carry (CF=0). Not supported in 64-bit mode.
0F 83 cd JNC rel32 D Valid Valid Jump near if not carry (CF=0).
0F 85 cw JNE rel16 D N.S. Valid Jump near if not equal (ZF=0). Not supported in 64-bit mode.
0F 85 cd JNE rel32 D Valid Valid Jump near if not equal (ZF=0).
0F 8E cw JNG rel16 D N.S. Valid Jump near if not greater (ZF=1 or SF≠ OF). Not supported in 64-bit mode.
0F 8E cd JNG rel32 D Valid Valid Jump near if not greater (ZF=1 or SF≠ OF).
0F 8C cw JNGE rel16 D N.S. Valid Jump near if not greater or equal (SF≠ OF). Not supported in 64-bit mode.
0F 8C cd JNGE rel32 D Valid Valid Jump near if not greater or equal (SF≠ OF). 
0F 8D cw JNL rel16 D N.S. Valid Jump near if not less (SF=OF). Not supported in 64-bit mode.
0F 8D cd JNL rel32 D Valid Valid Jump near if not less (SF=OF).
0F 8F cw JNLE rel16 D N.S. Valid Jump near if not less or equal (ZF=0 and SF=OF). Not supported in 64-bit mode.
0F 8F cd JNLE rel32 D Valid Valid Jump near if not less or equal (ZF=0 and SF=OF).
0F 81 cw JNO rel16 D N.S. Valid Jump near if not overflow (OF=0). Not supported in 64-bit mode.
0F 81 cd JNO rel32 D Valid Valid Jump near if not overflow (OF=0).
0F 8B cw JNP rel16 D N.S. Valid Jump near if not parity (PF=0). Not supported in 64-bit mode.
0F 8B cd JNP rel32 D Valid Valid Jump near if not parity (PF=0).
0F 89 cw JNS rel16 D N.S. Valid Jump near if not sign (SF=0). Not supported in 64-bit mode.
0F 89 cd JNS rel32 D Valid Valid Jump near if not sign (SF=0).
0F 85 cw JNZ rel16 D N.S. Valid Jump near if not zero (ZF=0). Not supported in 64-bit mode.
0F 85 cd JNZ rel32 D Valid Valid Jump near if not zero (ZF=0).
0F 80 cw JO rel16 D N.S. Valid Jump near if overflow (OF=1). Not supported in 64-bit mode.
0F 80 cd JO rel32 D Valid Valid Jump near if overflow (OF=1).
0F 8A cw JP rel16 D N.S. Valid Jump near if parity (PF=1). Not supported in 64-bit mode.
0F 8A cd JP rel32 D Valid Valid Jump near if parity (PF=1).
0F 8A cw JPE rel16 D N.S. Valid Jump near if parity even (PF=1). Not supported in 64-bit mode.
0F 8A cd JPE rel32 D Valid Valid Jump near if parity even (PF=1).
0F 8B cw JPO rel16 D N.S. Valid Jump near if parity odd (PF=0). Not supported in 64-bit mode.
0F 8B cd JPO rel32 D Valid Valid Jump near if parity odd (PF=0).
0F 88 cw JS rel16 D N.S. Valid Jump near if sign (SF=1). Not supported in 64-bit mode.
0F 88 cd JS rel32 D Valid Valid Jump near if sign (SF=1).
0F 84 cw JZ rel16 D N.S. Valid Jump near if 0 (ZF=1). Not supported in 64-bit mode.
0F 84 cd JZ rel32 D Valid Valid Jump near if 0 (ZF=1).
</code></pre>
<p dir="auto">Если трейсить трейслогом 1000 инструкций поверх call, то видим многократное повторение пути внутри цикла между 00437A34 и 0044DFAF.<br />
<img src="/assets/uploads/files/1680390556707-1d498e8e-9dce-4fd3-8327-6b8551202bb1-%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5.png" alt="1d498e8e-9dce-4fd3-8327-6b8551202bb1-изображение.png" class=" img-fluid img-markdown" /><br />
С помощью скрипта можно выйти на цикл не используя трейслог</p>
<p dir="auto">Можно использоваться функции определения куда прыгнет поток, до его выполнения.</p>
<p dir="auto">Можно оперировать таблицей адресов с брейкпоинтами в пошаговой отладке.</p>
]]></description><link>https://celua.ru/topic/31/выход-из-рутины-до-ближайшего-цикла</link><generator>RSS for Node</generator><lastBuildDate>Wed, 17 Jun 2026 12:40:55 GMT</lastBuildDate><atom:link href="https://celua.ru/topic/31.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 01 Apr 2023 23:09:47 GMT</pubDate><ttl>60</ttl></channel></rss>