Код в студии Код (Text): .286 ;.model flat,stdcall StackSg SEGMENT Stack StackSg ENDS DataSG SEGMENT PARA 'data' STACK_ STRUC first dw ? cur dw ? last dw ? STACK_ ends MYSTACK STACK_ ? MemForStack dw 1024 dup(0) temp dw 3; DataSG ENDS CodeSg SEGMENT PARA 'code' ASSUME CS: CodeSg, DS: DataSG, SS: StackSg, ES: Nothing MAIN PROC jmp @START ; ;(DS, ADDRES_STACK,DWORD DATA) PUSH_STACK PROC FAR push bp mov bp,sp push ds push ax push cx push dx mov ds,[bp+0Ah] mov dx,[bp+06] mov ax,bp mov bp,[bp+08] mov cx,WORD PTR ds:STACK_[bp].last cmp WORD PTR ds:STACK_[bp].cur,cx jns @L0 mov cx,offset ds:STACK_[bp].cur xchg cx,bp mov ds:[bp],dx xchg bp,cx ; - - - mov cx,ax mov ax,WORD PTR ds:STACK_[bp].cur add ax,2 mov WORD PTR ds:STACK_[bp].cur,ax mov ax,cx ; - - - - - @L0: mov bp,ax pop dx pop cx pop ax pop ds pop bp ret 6 PUSH_STACK ENDP ; ;(DS, ADDRES_STACK, VALUE) ;(DS, ADDRES_STACK,DWORD DATA) POP_STACK PROC FAR push bp mov bp,sp push ds push ax push cx push dx push bx mov ds,[bp+0Ah] mov dx,[bp+06] mov ax,bp mov bp,[bp+08] mov cx,WORD PTR ds:STACK_[bp].first cmp WORD PTR ds:STACK_[bp].cur,cx js @L1 mov bx,bp ; ў бе ЇЁиҐвбп ¤аҐб § зҐЁп ў б⥪Ґ mov bp,ds:STACK_[bp].cur ;ў cе § 票Ґ Ё§ б⥪ mov cx,ds:[bp] ; ЇЁиҐ¬ § 票Ґ Ё§ бе, ў ¤аҐбб Єг¤ ¤® § ЇЁб вм mov bp,dx mov ds:[bp],cx ;ў®бв ў«Ёў Ґ¬ bp, Ё 㬥ми Ґ¬ STACK_.cur mov bp,bx mov cx, ds:STACK_[bp].cur sub cx,2 mov WORD PTR ds:STACK_[bp].cur,cx @L1: mov bp,ax pop bx pop dx pop cx pop ax pop ds pop bp ret 6 POP_STACK ENDP @START: mov MYSTACK.first,offset MemForStack mov MYSTACK.cur,offset MemForStack mov MYSTACK.last,offset MemForStack add MYSTACK.last,255*2 push offset ds push offset MYSTACK push 3 call PUSH_STACK push offset ds push offset MYSTACK push offset temp call POP_STACK push offset ds push offset MYSTACK push 17 call PUSH_STACK push offset ds push offset MYSTACK push 7 call PUSH_STACK push offset ds push offset MYSTACK push 5 call PUSH_STACK MOV Ax,4C00H INT 21H MAIN ENDP CodeSG ENDS END MAIN
Код (Text): .286 ;.model flat,stdcall StackSg SEGMENT Stack ; << Сюда стоит добавить хотя бы dw 10 dup (?) иначе операции со стеком пойдут тереть PSP программы (т.к. сегмент стека находится в самом начале образа, то перед ним в памяти будет только PSP) и это плохо закончится при ее завершении (это ответ на вопрос про не допустимую операцию после mov ax, 19456/int 33) StackSg ENDS DataSG SEGMENT PARA 'data' STACK_ STRUC first dw ? cur dw ? last dw ? STACK_ ends MYSTACK STACK_ ? MemForStack dw 1024 dup(0) temp dw 3; <<<< Интерестно. Чему будет равно i после следующего выражения if i=3 then i:=i else i:=3; ; также и у Вас. Чему будет равна переменная temp если она инициализируется значением 3, потом вы в свой стек кладете значение 3 и достается его в эту переменную DataSG ENDS CodeSg SEGMENT PARA 'code' ASSUME CS: CodeSg, DS: DataSG, SS: StackSg, ES: Nothing MAIN PROC jmp @START; < Чес слово. Так и не понял смысл этого jmp'а. Почему основной код нельзя разместить здесь, а процедуры push и pop вынести за пределы main'а в конец ; ;(DS, ADDRES_STACK,DWORD DATA) PUSH_STACK PROC FAR push bp mov bp,sp push ds push ax; <<<<<< Вот чес слово. лучше бы вместо сx и dx использовали бы si и di push cx push dx mov ds,[bp+0Ah] mov dx,[bp+06];mov ax, [bp+6] - значение mov ax,bp; это вообще ни к чему mov bp,[bp+08];mov di, [bp+8] - стек ; assume di:STACK_ mov cx,WORD PTR ds:STACK_[bp].last; mov si, [di].cur cmp WORD PTR ds:STACK_[bp].cur,cx ;cmp si, [di].last jns @L0 ; у вас в стеке еще и указатели знаковые - поздравляю; jc @L0 mov cx,offset ds:STACK_[bp].cur; это не нужно тогда xchg cx,bp; и это тоже mov ds:[bp],dx; mov [si], ax xchg bp,cx; и это тоже не нужно ; - - - mov cx,ax ; это не нужно. . . mov ax,WORD PTR ds:STACK_[bp].cur add ax,2 mov WORD PTR ds:STACK_[bp].cur,ax mov ax,cx ; . . .все аж до сих пор. вместо этого просто add [di].cur, 2 ; - - - - - @L0: mov bp,ax; это вообще ни к чему ;assume di:none pop dx pop cx pop ax pop ds pop bp ret 6 PUSH_STACK ENDP ; ;(DS, ADDRES_STACK, VALUE) ;(DS, ADDRES_STACK,DWORD DATA) POP_STACK PROC FAR push bp mov bp,sp push ds push ax push cx push dx push bx ; тут те же проблемы что и в push mov ds,[bp+0Ah] mov dx,[bp+06]; mov si, [bp+6] mov ax,bp; не нужно (тоже мне нашли куда bp сохранить) mov bp,[bp+08]; mov di, [bp+8] mov cx,WORD PTR ds:STACK_[bp].first; mov ax, [di].cur cmp WORD PTR ds:STACK_[bp].cur,cx ; cmp ax, [di].first js @L1; опять знаковые указатели ja @L1 ; до метки @L1 даже не стал читать. это вообще все лучше переписать mov bx,bp ; ў бе ЇЁиҐвбп ¤аҐб § зҐЁп ў б⥪Ґ mov bp,ds:STACK_[bp].cur ;ў cе § 票Ґ Ё§ б⥪ mov cx,ds:[bp] ; ЇЁиҐ¬ § 票Ґ Ё§ бе, ў ¤аҐбб Єг¤ ¤® § ЇЁб вм mov bp,dx mov ds:[bp],cx ;ў®бв ў«Ёў Ґ¬ bp, Ё 㬥ми Ґ¬ STACK_.cur mov bp,bx mov cx, ds:STACK_[bp].cur sub cx,2 mov WORD PTR ds:STACK_[bp].cur,cx ;push bp ;mov bp, sp ;push si ;push di ;push ax ;mov di, [bp+6] ;mov si, [bp+8] ;push ds ;mov ds, [bp+10] ; assume si:STACK_ ;mov ax, [si].cur ;cmp [si].first, ax ;jae @L1 ;sub [si].cur, 2 ;mov si, [si].cur ;mov ax, [si] ;pop ds ;mov [di], ax ;push ds ;@L1: ; assume si:none ;pop ds ;pop ax ;pop di ;pop si ;pop bp ;ret 6 ; сами надеюсь разберетесь @L1: mov bp,ax pop bx pop dx pop cx pop ax pop ds pop bp ret 6 POP_STACK ENDP @START: mov MYSTACK.first,offset MemForStack mov MYSTACK.cur,offset MemForStack mov MYSTACK.last,offset MemForStack add MYSTACK.last,255*2; <<<<< А нельзя сразу mov MYSTACK.last,offset MemForStack[255], ну или если тасм не догадается умножить 255 на размер word'а, то mov MYSTACK.last,offset MemForStack[255*2] push offset ds ; <<< И тасм это проглатывает. интерестно бы узнать, какое значение он туда загоняет или во что это компилируется. Смещение в программе сегментного регистра это весело. Правильнее было бы написать push ds push offset MYSTACK push 3 call PUSH_STACK push offset ds push offset MYSTACK push offset temp call POP_STACK push offset ds push offset MYSTACK push 17 call PUSH_STACK push offset ds push offset MYSTACK push 7 call PUSH_STACK push offset ds push offset MYSTACK push 5 call PUSH_STACK MOV Ax,4C00H INT 21H MAIN ENDP CodeSG ENDS END MAIN
XshStasX, 16-битный режим не так богат на варианты употребления базовых/индексных регистров (это тов. krabz верно заметил), как 32/64-битный. По сути вопроса стоит посмотреть табличку 2-1 в подразделе 2.1.5 Intel SDM — там всё про возможности адресации памяти в 16-ти битах показано наглядно (ага, никаких sp). То, что пересылка чего-то в ax не меняет старшую часть eax не должно вызывать ни сомнений, ни удивления. Как и то, что с соответствующим(и) префиксами 16-битная инструкция может использовать как 32-битную адресацию, так и 32-битные регистры.