>

어셈블리를 배우기 시작하면서, 나는 리눅스에서 수업하는 동안 만들어진 Hello World 어셈블리 코드를 받았다. 64 비트 Mac OS X에서 작동하도록하고 싶습니다.

code.asm:

SECTION .data       
    hola:   db "Hola!",10   
    tam:    equ $-hola      
SECTION .text       
    global main     
main:               
    mov edx,tam     
    mov ecx,hola        
    mov ebx,1       
    mov eax,4       
    int 0x80        
    mov ebx,0       
    mov eax,1       
    int 0x80       

이것이 내가하는 일 :

nasm -f macho32 -o object.o code.asm
gcc -m32 -o program object.o

나에게 말해줘 :

Undefined symbols for architecture i386: "_main", referenced from: start in crt1.10.6.o ld: symbol(s) not found for architecture i386

이 오류를 검색하면서 nasm 및 gcc : 32 비트 연결 실패 (64 비트 Mac OS X)

하나의 답변

The problem you're having is that you're creating a 32-bit Linux(ELF) object file which isn't compatible with the Mac OS X object format. Try switching '-f elf' to '-f macho32'.

그러나 나는 -f macho32 를 확실히 사용하고 있습니다. . 그렇다면 문제는 무엇입니까?

  • 답변 # 1

    저도 엔트리 레벨 어셈블리 프로그래밍을 가르치려고 노력하고 있는데 비슷한 문제가 발생했습니다. 원래 nasm 를 사용하여 컴파일했습니다.   elf 와 함께 하지만 ld 를 사용하려고 시도했지만 작동하지 않았습니다.  개체 파일을 연결하고 실행 파일을 만듭니다.

    답은 당신이 주된 질문이라고 생각합니다   "what would the problem be then?" [to get this to run on 64bit MacOSX] 를 사용하고 있습니다  64 비트 시스템에서 실행될 것으로 예상하려면 명령 옵션을 -f macho32 로 변경해야합니다. .물론 어셈블리 코드가 다른 아키텍처 용으로 작성되었다는 사실을 해결하지는 못합니다.

    이 인스턴스에서 코드를 컴파일하고 링크하기 위해 올바른 명령 에서이 편리한 답변을 찾았습니다 (어느 말로 * nix 대신 올바른 구문을 사용하도록 어셈블리 코드를 리팩터링 한 후) : -f macho64

    일부 검색 한 후 여기에 내가 배운 내용이 있습니다 ... <올>

    Mac 64 비트에서는 nasm -f macho64 main.asm -o main.o && ld -e _main -macosx_version_min 10.8 -arch x86_64 main.o -lSystem 를 사용하는 것이 좋습니다.   as 대신 어셈블러  (보다 자연스러운 것을 원한다면) 더 이식 가능한 코드를 원한다면 (차이점을 배우십시오)

    nasm  기본적으로 macho64 출력 유형이 설치되어 있지 않습니다

    어셈블리는 키스 터의 고통입니다 (이것은 제쳐두고)

    이제 학습 격차가 사라졌습니다 ...

    nasm 를 사용하여 MacOSX 64에서 작동해야하는 코드는 다음과 같습니다.  ( nasm 를 업데이트 한 경우   nasm 와 함께 , Dustin Schultz의 신용) :

    macho64
    
    

    내가 section .data hello_world db "Hello World!", 0x0a section .text global start start: mov rax, 0x2000004 ; System call write = 4 mov rdi, 1 ; Write to standard out = 1 mov rsi, hello_world ; The address of hello_world string mov rdx, 14 ; The size to write syscall ; Invoke the kernel mov rax, 0x2000001 ; System call number for exit = 1 mov rdi, 0 ; Exit success = 0 syscall ; Invoke the kernel 와 함께 사용하는 작업 코드  MacOSX64 기본 어셈블러 :

    as
    
    

    컴파일 명령 : .section __TEXT,__text .global start start: movl $0x2000004, %eax # Preparing syscall 4 movl $1, %edi # stdout file descriptor = 1 movq [email protected](%rip), %rsi # The string to print movq $100, %rdx # The size of the value to print syscall movl $0, %ebx movl $0x2000001, %eax # exit 0 syscall .section __DATA,__data str: .asciz "Hello World!\n"

    링크 명령 : as -arch x86_64 -o hello_as_64.o hello_as_64.asm

    명령 실행 : ld -o hello_as_64 hello_as_64.o

    여행 중에 찾은 몇 가지 유용한 자료 :

    ./hello_as_64  OSX 어셈블러 참조: https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/Assembler/Assembler.pdf

    Mac OSX에서 64 비트 어셈블리 작성: http://www.idryman.org/blog/2014/12/02/writing-64-bit-assembly-on-mac-os- x/

    AS 를 사용하여 객체 파일을 연결할 수 없습니다 : ld-Mac OS X를 사용하여 객체 파일을 연결할 수 없음

    OSX i386 SysCalls: http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/mach/i386/syscall_sw.h

    OSX 마스터 시스템 호출 정의: http://www.opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master

    OSX Syscall: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/syscall.2.html

  • 답변 # 2

    다음을 수행해야합니다.

    <올>

    ld 에서 라벨 이름 변경   main 로  (두 곳에서). Mac OS X에서는 심볼 이름이 약간 다르게 작동합니다.

    시스템 호출에 인수를 전달하는 방식을 변경하십시오. Mac OS X은 Linux와 다른 커널 호출 규칙을 사용합니다. 이 코드는 이식성이없습니다입니다! 작동 방식에 대한 공식 문서가 있는지 모르겠지만 _main 와 같은 표준 라이브러리 기능에 대한 GDB의 분해를 살펴보십시오.  도움이 될 수 있습니다.

    여기 _exit()  예를 들어 내 시스템에서 :

    _exit
    
    

    <_exit+0>: mov $0x40001,%eax <_exit+5>: call 0x96f124c2 <_sysenter_trap> <_exit+10>: jae 0x96f10086 <_exit+26> <_exit+12>: call 0x96f1007d <_exit+17> <_exit+17>: pop %edx <_exit+18>: mov 0x15a3bf9f(%edx),%edx <_exit+24>: jmp *%edx <_exit+26>: ret <_exit+27>: nop 에서 설정 한 여분의 비트  ... 이상하지만 여기서 안전하게 무시할 수 있습니다.

    와이즈 비즈의 부름에 따른 것들  오류 처리를위한 것입니다.

    0x40001  입니다 :

    _sysenter_trap
    
    

    모든 것을 고려하면 커널을 직접 호출하는 대신 libSystem (libx와 동일한 OS X)에 연결하는 것이 좋습니다.

    _sysenter_trap

관련 자료

  • 이전 java : 자바 : 재귀 적으로 다이아몬드를 인쇄하십시오
  • 다음 javascript - 메뉴 항목의 양에 따라 메뉴 항목의 너비 변경