2011-08-01 2 views
5

좋은 참고가 필요할 수도 있지만 좋은 예가 필요할 것입니다. 내가 NASM 어셈블러를 사용하여 어셈블리에 코드를 작성하기 시작했기 때문에 필요합니다. 나는이 참조가 : 매우 좋은 유용syscalls에 대한 좋은 참조

http://bluemaster.iu.hio.no/edu/dark/lin-asm/syscalls.html

을하지만, 다른 레지스터의 필드를 설명하지 않기 때문에 그것은 많은 제약을 가지고있다. 예를 들어 write syscall을 사용하고 있다면 EAX 레지스터에 1을 넣어야하고 ECX는 아마도 문자열에 대한 포인터이지만 EBX와 EDX는 어떨까요? EBX가 입력 (stdin은 0, 다른 것은 1 등)을 결정하고 EDX는 입력 할 문자열의 길이 등을 설명합니다. 원하는 것을 이해했으면합니다. , 나는 그런 자료를 찾을 수 없었습니다. 그래서 제가 여기서 글을 쓰고 있습니다. 미리 감사드립니다.

답변

0

웹 페이지를 다운로드하고 (두 번째 단락에서 제안하는 것처럼) 커널 소스를 다운로드하는 경우 "소스"열의 링크를 클릭하고 시스템 호출을 구현하는 소스 파일로 직접 이동할 수 있습니다. 각 매개 변수가 사용되는 것을보기 위해 C 서명을 읽을 수 있습니다.

빠른 참조 만 찾고 계시다면, 각 시스템 호출에는 동일한 이름에서 sys_을 뺀 C 라이브러리 인터페이스가 있습니다. 따라서 예를 들어, 당신은 sys_lseek의 매개 변수에 대한 정보를 얻기 위해 man 2 lseek을 확인할 수 있습니다 :

%ebx   %ecx %edx 
unsigned int off_t unsigned int 
+0

물론 Google에서 각 검색을 수행하거나 소스 코드를 검색하여 구현하는 경우에도 직접 사용 된 사례를 찾을 수 있습니다. 내 게시물의 요점은 검색 및 일부 좋은 치트 시트와 분석을 건너는 것입니다. 감사. –

11
: 당신이 볼 수 있듯이, 매개 변수가 HTML 테이블에서 사람과 일치

off_t lseek(int fd, off_t offset, int whence); 

Linux의 표준 프로그래밍 언어는 C입니다.이 때문에 시스템 호출의 가장 좋은 설명은 호출 할 C 함수로 표시됩니다. C 함수로서의 설명과이를 어셈블리에서 실제 시스템 호출에 매핑하는 방법에 대한 지식이 있으면 원하는 시스템 호출을 쉽게 사용할 수 있습니다.

먼저 C 프로그래머에게 표시되는 모든 시스템 호출에 대한 참조가 필요합니다. 내가 아는 가장 좋은 것은 Linux man-pages project이며, 특히 system calls 섹션입니다.

write 시스템 호출은 예제의 시스템 호출을 예로 들어 봅시다. 보시다시피 첫 번째 매개 변수는 부호가있는 정수이며 일반적으로 open 시스템 호출에 의해 반환 된 파일 설명 자입니다. 이러한 파일 설명자는 부모 프로세스에서 상속되었을 수도 있습니다. 일반적으로 처음 세 파일 설명자 (0 = stdin, 1 = stdout, 2 = stderr)에서 발생합니다. 두 번째 매개 변수는 버퍼에 대한 포인터이고 세 번째 매개 변수는 버퍼 크기 (부호없는 정수)입니다. 마지막으로 함수는 부호있는 정수 (기록 된 바이트 수 또는 음수)를 반환합니다.

이제 이것을 실제 시스템 호출에 매핑하는 방법은 무엇입니까? 32 비트 x86에서 시스템 호출을 수행하는 방법에는 여러 가지가 있습니다 (레지스터 이름을 기반으로 사용하는 것일 수 있습니다). 64 비트 x86에서는 32 비트 모드로 어셈블하고 32 비트 실행 파일을 연결해야합니다 (다른 방법이 잘못 될 수있는 예에 대해서는 this question을 참조하십시오). 가장 오래된 것 중 가장 간단하고 가장 느린 것은 32 비트 x86에서 int $0x80 메서드입니다.

int $0x80 방법의 경우, %eax에서 시스템 콜 번호를 넣어의 매개 변수 %ebx, %ecx, %edx, %esi, %edi%ebp, 순서입니다. 그런 다음 int $0x80을 호출하고 시스템 호출의 반환 값은 %eax입니다. 이 반환 값은 이고 다른 참조 번호는입니다. 참조는 C 라이브러리가이를 리턴하는 방법을 보여 주지만 시스템 호출은 오류시 -errno을 리턴합니다 (예 : -EINVAL). 이 경우 C 라이브러리는 errno으로 이동하고 -1을 반환합니다. 자세한 내용은 syscalls(2)intro(2)을 참조하십시오.

그래서, write 예를 들어, 당신은 (%eax에서 write 시스템 호출 번호, %ebx의 첫 번째 매개 변수 (파일 기술자 번호), %ecx에서 두 번째 매개 변수 (문자열 포인터), 그리고 세 번째 매개 변수를 둘 것 문자열의 길이)는 %edx입니다. 시스템 콜은 %eax에 쓰여진 바이트 수를 반환하거나 에러 번호를 무효화합니다 (반환 값이 -1과 -4095 사이 인 경우 부정 된 에러 번호).

마지막으로 어떻게 시스템 호출 번호를 찾으십니까? 그들은 /usr/include/linux/unistd.h에서 찾을 수 있습니다. 내 시스템에는 /usr/include/asm/unistd.h이 포함되어 있으며, 마지막으로 /usr/include/asm/unistd_32.h이 포함되어 숫자가 있습니다 (write의 경우 __NR_write4입니다). /usr/include/linux/errno.h에서 오는 오류 번호도 마찬가지입니다 (내 시스템에서 포함 체인을 추적 한 후 첫 번째 코드는 /usr/include/asm-generic/errno-base.h이고 나머지는 /usr/include/asm-generic/errno.h). 다른 상수 나 구조체를 사용하는 시스템 호출의 경우 해당 문서에서 해당 정의를 찾으려면 어떤 헤더를 봐야하는지 알려줍니다. 내가 말했듯이


지금, int $0x80는 가장 오래되고 가장 느린 방법입니다. 최신 프로세서에는보다 빠른 특수 시스템 호출 명령어가 있습니다. 커널을 사용하기 위해 하드웨어에서 사용할 수있는 최상의 방법을 사용하여 시스템 호출을 수행 할 수있는 함수를 사용하여 가상 동적 공유 객체 (vDSO, 공유 라이브러리와 같지만 메모리에만 있음)를 사용할 수 있습니다. 또한 시스템 호출을하지 않고도 현재 시간을 알 수있는 특별한 기능을 제공합니다. 물론, 동적 링커를 사용하지 않는다면 사용하기가 조금 더 어렵습니다.

또 다른 구식 방법 인 vsyscallvDSO과 유사하지만 고정 주소에서 단일 페이지를 사용합니다. 이 방법은 더 이상 사용되지 않으며, 최근 커널을 사용하고 더 최근의 커널에서 부팅 할 때 비활성화 할 수 있으며 나중에 제거 될 수있는 경우 시스템 로그에 경고가 표시됩니다. 사용하지 마십시오.

+0

이것은 내가 본 최고의 답변 중 하나입니다. –