codememo

일반 프로그램이 보통 0x8000에서 시작하는 이유는 무엇입니까?

tipmemo 2023. 6. 27. 22:15
반응형

일반 프로그램이 보통 0x8000에서 시작하는 이유는 무엇입니까?

부트로더와 시스템 SW는 처음은 아니지만, 일반 프로그램이 시작되는 이유가 무엇인지는 모르겠습니다.0x8000나는 이미 주소를 알고 있습니다.0x8000는 일반 C/C++ 프로그램에서 시작 주소로 사용되었습니다.

일반 프로그램에 대한 부트로더의 최소 크기는 다음과 같습니까?0x8000아니면 부트로더에 할당해야 하는 ROM의 최소 블록 크기가 32KB입니까?아니면 다른 이유가 있나요?

역사적으로나 논리적으로나 가상 주소의 관점에서 이에 대해 알고 싶습니다.


시간을 내주시고 도와주셔서 감사합니다.질문을 좀 더 명확히 하기 위해, 질문은 물리적인 것이 아니라 가상 주소와 관련이 있습니다.

저는 기본적으로 물리적 메모리 주소의 관점에서 R의 의견에 동의합니다.

Linux(안드로이드에서도 가능), 일반 RTOS(핵 및 기타, 특히 ARM 링커 섹션)와 같이 다양한 특정 시스템을 말하지 않고 모두 주소 0x8000을 시작 주소 일반 프로그램으로 사용합니다.로더가 있는 0x0에 위치한 crt_dll.o, crt.o 등의 이름이 이 영역에 존재합니다.

따라서 일반 프로그램용 부트로더의 최소 크기는 부트 시 부트롬(콜드 부트)에 위치할 경우 블록 크기를 고려하여 32KB로 예상됩니다.

음, 하지만 잘 모르겠어요...

일반적으로 가장 작은 임베디드 시스템을 제외한 모든 시스템에서 플랫폼 ABI 설계자는 Null 포인터 참조가 트랩될 수 있도록 사용 중인 주소가 가장 낮은 것을 피하고자 합니다.null 포인터가 배열 또는 구조체 멤버 오프셋과 참조되지 않는 경우 유효하지 않은 주소가 여러 KB 있으면 추가적인 안전성을 제공합니다.null_ptr->some_member.

이는 시스템에 따라 다르며 프로그램은 서로 다른 시스템의 서로 다른 주소에서 시작됩니다.유닉스에서는 주소 0을 널 포인터로 사용하고 가상 메모리의 첫 페이지를 매핑하지 않는 것이 일반적이며(또는 Posix에 의해 요구될 수도 있음) 널 포인터를 다시 참조하면 세그먼트 위반이 발생합니다.주소 0을 null 포인터로 사용하는 다른 시스템도 유사하게 동작할 것으로 예상됩니다(그러나 예약량은 다를 수 있습니다).(역사적으로, 첫 페이지를 읽기 전용으로 매핑하고 0으로 채우는 것이 일반적이었습니다. null 포인터가 빈 문자열인 것처럼 행동했습니다.""하지만 그것은 약 25년 전으로 거슬러 올라갑니다.)

오늘날에도 일부 임베디드 시스템은 주소 0에서 시작하는 프로그램을 로드합니다.

그것은 다소 임의적이며, 리눅스에서는 적어도 링커에 의해 결정됩니다.일반적인 아이디어는 NULL 포인터 예외를 포착하기 위해 공간을 예약하는 것입니다.커널 공간 NULL 포인터 참조가 커널 모드에서 임의 사용자 코드를 실행하는 것을 방지하기 위해 Linux를 사용하면 메모리 맨 아래 부분을 매핑할 수 없습니다. /proc/sys/vm/mmap_min_addr에서는 매핑할 수 있는 가장 낮은 주소를 제어합니다(원하는 경우 0으로 변경하고 페이지를 0으로 매핑할 수 있습니다).

리눅스에서 당신은 메모리 매핑을 볼 수 있습니다./proc.예를들면,

genwitt ~> 고양이/고양이/자기/고양이00400000-0040c000 r-xp 00000000 08:01 354804 /bin/cat0060b000-0060c000 r--p 0000b000 08:01 354804 /bin/cat0060c000-0060d000 rw-p 0000c000 08:01 354804 /bin/cat01 dda000-01dfb000 rw-p 0000000000:00 [개별]7f5b25913000-7f5b25a97000 r-xp000000 08:01 435953 /lib64/libc-2.14.1.so7f5b25a97000-7f5b25c97000 ---p 00184000 08:01 435953 /lib64/libc-2.14.1.so7f5b25c97000-7f5b25c9b000 r--p 00184000 08:01 435953 /lib64/libc-2.14.1.so7f5b25c9b000-7f5b25c9c000 rw-p 00188000 08:01435953 /lib64/libc-2.14.1.so7f5b25c9c000-7f5b25ca1000rw-p000000:00007f5b25ca1000-7f5b25cc2000 r-xp000000 08:01 436061 /lib64/ld-2.14.1.so7f5b25cd2000-7f5b25e97000 r--p 00000000 08:01 126248 /usr/lib64/slot/slot/slot-slots7f5b25e97000-7f5b25e9a000 rw-p 00000000:00007f5b25ec0000-7f5b25ec1000rw-p 00000000:00007f5b25ec1000-7f5b25ec2000 r--p 00020000 08:01 436061 /lib64/ld-2.14.1.so7f5b25ec2000-7f5b25ec3000 rw-p00021000 08:01 436061 /lib64/ld-2.14.1.so7f5b25ec3000-7f5b25ec rw-p 00000000:00007fff18c37000-7ff18c58000 rw-p 00000000:00 [스택]7ffff18d0c000-7ff18d0d000 r-xp000000:00 [vdso]fffffffff600000-ffffff601000 r-xp 00000000:00 [vsyscall]

대부분의 경우 처음 32K는 모니터 코드/램 사용을 위해 예약되어 있습니다.많은 8051 평가 보드에서 상주 모니터(일부는 디버거로도 작동)에 따라 모든 앱에 대해 0x1000 또는 0x2000으로 기본 설정되는 경우가 그리 드물지 않았습니다.

32K는 u-boot/etc 로더 공간일 수 있습니다.

저는 그 답이 인터럽트 처리와 더 관련이 있다고 생각합니다.인터럽트 핸들러 주소는 하드웨어에서 설정됩니다.Intel 8086에는 인터럽트 핸들러 코드와 해당 인터럽트 처리 루틴에 직접 변환 테이블이 있었습니다.이 작업은 일부 조합 회로에 의해 수행되었으므로 상위 호환성을 유지하기 위해 매번 변경되지 않도록 메모리의 끝에 배치하는 것이 더 현명했을 것입니다.실행 시작 주소는 메모리의 다른 쪽 끝에 있습니다.또한 메모리 세그먼트 프로그램을 로드하기 위한 충분한 코드와 해당 코드 주소에서 코드를 실행하기 위한 전환을 위한 점프 명령이 해당 블록에 포함되어야 했습니다.

언급URL : https://stackoverflow.com/questions/9679352/why-does-the-general-program-usually-start-at-0x8000

반응형