Что делает PUSHing адрес до того, как выполнение достигает другой функции с RET? - PullRequest
0 голосов
/ 19 декабря 2018

Почему мы храним значение SECONDRELOCATION в AX, а затем почему мы помещаем AX в стек

Я изучаю основы программирования MSDOS, я не могу понять, как и почему управление передается между тремяСМЕЩЕНИЯ (в строке 1, строке 43 и строке 53. Эти строки явно указаны мной в качестве комментариев)

    CLI
    MOV     AX,CS
    MOV     SS,AX
    MOV     SP,OFFSET LOCSTACK  ;line4

    ASSUME  SS:SYSINITSEG

    IF      NOT ALTVECT
    STI                             ; Leave INTs disabled 
                                    ;for ALTVECT
    ENDIF
    LOCSTACK LABEL BYTE

    CALL    MSDOS
    MOV     WORD PTR [DOSINFO+2],ES ; SAVE POINTER TO DOS 
                                    ;INFO
    MOV     WORD PTR [DOSINFO],DI

    IF      NOT IBM
    IF      NOT IBMJAPVER
    CALL    RE_INIT                 ; Re-call the BIOS
    ENDIF
    ENDIF

    STI
    CLD

    IF      HIGHMEM
    PUSH    DS
    MOV     BX,DS
    ADD     BX,10H
    MOV     ES,BX
    PUSH    CS
    POP     DS
    XOR     SI,SI
    MOV     DI,SI
    MOV     CX,OFFSET SYSSIZE + 1
    SHR     CX,1                    ; Divide by 2 to get 
                                    ;words
    REP     MOVSW
    POP     DS
    PUSH    ES
    MOV     AX,OFFSET SECONDRELOC ;line43 (why we are storing offset value 
                                  ;of SECONDRELOC in AX, if we are moving 
                                  ;there already ofter RE_INIT PROC one more 
                                  ;point is that why we are PUSHing AX value 
                                  ;in stack)
    PUSH    AX  ;<-------
    RE_INIT PROC    FAR
    ....some code here..... 
    RET
    RE_INIT ENDP

    SECONDRELOC:
    MOV     AX,CS
    CLI
    MOV     SS,AX
    MOV     SP,OFFSET LOCSTACK    ;line53
    STI

1 Ответ

0 голосов
/ 25 декабря 2018

Используется push / push / ret far в качестве jmp для абсолютного смещения в переменном целевом сегменте.Он извлекает новый CS: IP из стека, в данном случае ES:SECONDRELOC.

На самом деле, они хотят попасть в функцию RE_INIT с «поддельным» обратным адресом CS: IP.

x86 имеет jmp ptr16:16, который может перейти к абсолютному сегменту: off, но он работает только с жестко закодированным сегментом и смещением.Таким образом, единственный способ сделать дальний переход (установка новой CS, а также IP) с сегментом и / или смещением переменной времени выполнения - это иметь оба в памяти для jmp [m16:16] или для стека для ret farчтобы вытащить их обоих.

Чтобы прыгать, не оставляя вещи в стеке и не резервируя какие-либо статические данные, far ret - единственный хороший вариант.(Существует также плохая опция самоизменения кода для изменения части сегмента jmp 0000:SECONDRELOC перед его выполнением, но это, вероятно, хуже для размера кода.)

Они mov значениесначала в AX, вместо использования push OFFSET SECONDRELOC напрямую, потому что push imm8 и push imm16 были добавлены только в 286. (См. приложение к старой версии руководства NASM: http://www.posix.nl/linuxassembly/nasmdochtml/nasmdoca.html. Поиск"push imm" на этой странице.)


Это то же самое, что и в коде, который вы показали в Какова цель PUSH CS / POP DS перед REP MOVSW? ,где я уже описал, как код выдвигает seg:off, а затем использует дальний ret для перехода к новому CS: IP.

...