x86 32 비트 머신 코드 조각, 1 바이트
48 dec eax
EAX 입력, EAX 출력 : true의 경우 0, false의 경우 0이 아님. (또한 ZF 플래그를 true로 설정하고 false로 설정하지 않은 상태로 두어도됩니다.je was_equal
있습니다. "보너스"로서 랩핑에 대해 걱정할 필요가 없습니다. 32 비트 x86은 4GiB의 메모리 만 처리 할 수 있으므로 M을 감싸서 찾 1 == 2**32 + 1
거나 찾을 수있을 정도로 크게 만들 수는 없습니다 .
호출 가능한 함수를 만들려면 0xC3
ret
0x48
M 번 반복 한 후 명령을 . (많은 언어가 경쟁 할 수 있도록 함수 본문이나 식만 반복하면되기 때문에 전체 수에 포함되지 않습니다).
프로토 타입 __attribute__((regparm(1))) int checkeqM(int eax);
GNU C의 regparm
x86 함수 속성으로 GNU C에서 호출 가능 , 같은-mregparm
EAX를 사용하여 첫 번째 정수 인수를 전달합니다.
예를 들어,이 완전한 프로그램은 2 개의 args와 명령어 + a의 JIT M 사본을 ret
버퍼로 가져간 다음 함수로 호출합니다. (실행 파일 힙 필요,로 컴파일 gcc -O3 -m32 -z execstack
)
/******* Test harness: JIT into a buffer and call it ******/
// compile with gcc -O3 -no-pie -fno-pie -m32 -z execstack
// or use mprotect or VirtualProtect instead of -z execstack
// or mmap(PROT_EXEC|PROT_READ|PROT_WRITE) instead of malloc
// declare a function pointer to a regparm=1 function
// The special calling convention applies to this function-pointer only
// So main() can still get its args properly, and call libc functions.
// unlike if you compile with -mregparm=1
typedef int __attribute__((regparm(1))) (*eax_arg_funcptr_t)(unsigned arg);
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc<3) return -1;
unsigned N=strtoul(argv[1], NULL, 0), M = strtoul(argv[2], NULL, 0);
char *execbuf = malloc(M+1); // no error checking
memset(execbuf, 0x48, M); // times M dec eax
execbuf[M] = 0xC3; // ret
// Tell GCC we're about to run this data as code. x86 has coherent I-cache,
// but this also stops optimization from removing these as dead stores.
__builtin___clear_cache (execbuf, execbuf+M+1);
// asm("" ::: "memory"); // compiler memory barrier works too.
eax_arg_funcptr_t execfunc = (eax_arg_funcptr_t) execbuf;
int res = execfunc(N);
printf("%u == %u => %d\n", N,M, res );
return !!res; // exit status only takes the low 8 bits of return value
}
비 PIE 실행 파일 은 가상 메모리에서 더 낮은 수준으로로드됩니다. 더 큰 연속적인 malloc을 할 수 있습니다.
$ gcc -g -O3 -m32 -no-pie -fno-pie -fno-plt -z execstack coderepeat-i386.c
$ time ./a.out 2747483748 2747483748 # 2^31 + 600000100 is close to as big as we can allocate successfully
2747483748 == 2747483748 => 0
real 0m1.590s # on a 3.9GHz Skylake with DDR4-2666
user 0m0.831s
sys 0m0.755s
$ echo $?
0
# perf stat output:
670,816 page-faults # 0.418 M/sec
6,235,285,157 cycles # 3.885 GHz
5,370,142,756 instructions # 0.86 insn per cycle
참고 GNU C가 지원하지 않는 개체가보다 큰 크기 ptrdiff_t
(32 비트 부호)하지만,malloc
그리고 memset
이 프로그램이 성공 때문에, 아직도 작동합니다.
ARM Thumb 머신 코드 조각, 2 바이트
3802 subs r0, #2
첫 번째 인수 r0
및 반환 값 r0
은 표준 ARM 호출 규칙입니다. 또한 플래그 ( s
접미사)를 설정합니다 . 재미있는 사실; 비 의 -flag-설정 버전sub
32 비트 폭의 명령어이다.
추가해야 할 반품 지침은 bx lr
입니다.
AArch64 머신 코드 조각, 4 바이트
d1001000 sub x0, x0, #0x4
64 비트 정수에서 작동합니다. 입출력x0
표준 호출 규칙에 따라의 . int64_t foo(uint64_t);
AArch64에는 Thumb 모드 (아직)가 없으므로 1 개의 명령이 최선입니다.
L
M
N
L*M
? 인지 여부를 반환해야 합니다 .