Сборка TASM большой модели процедуры (вызывается из C) матричного цикла - PullRequest
0 голосов
/ 21 января 2019

Написал процедуру в сборке 8086, которая получит от C следующее:

int *matrix[size], int size, int *num1, int *num2. 

Сначала я написал ее как маленькую модель, она отлично работала, когда я перешел на большую модель, она перестала работать правильно, я попытался изменить количество циклов, «указатель строк», добавленный на 4, «указатель столбцов», добавленный 2 (пробовал добавить 4 и наоборот).

Процедура должна проверять минимум (в абсолютном значении), означающий наименьшее | x-y |. Например, процедура получит число N, вычтет его из всех других чисел и всегда сохранит минимум | x-y |. После этого он будет перемещаться на N на одно число вперед и проверять то же самое с остальными числами, пока не будет проверена вся матрица.

C-код (в этом ничего нельзя изменить):

    #include <stdio.h>
    #include <stdlib.h>

    extern int getDiffMin(int *mat[], int size , int *num1 , int *num2);

        int main()
        {
            int 

diff , i, j , num1 , num2;
        int **mat = (int **)malloc(sizeof(int *) * 4); 
        for (i = 0; i < 4; i++)
            mat[i] = (int *)malloc(sizeof(int) * 4);
        for (i = 0; i < 4; i++)
            for (j = 0; j < 4; j++)
                mat[i][j] = (i*j) - (5 * i) - (14 * j);
        for (i = 0; i < 4; i++)
        {
            for (j = 0; j < 4; j++)
                printf("%d\t", mat[i][j]);
            printf("\n");
        }
        diff = getDiffMin(mat, 4 , &num1 , &num2);
        printf("\nminDiff == |(%d)-(%d)| = %d", num1 , num2 , diff);
        for (i = 0; i < 4; i++)
            free(mat[i]);
        free(mat);
        return 0;
    }

Код сборки:

;extern int getDiffMin(int *mat[], int size , int *num1 , int *num2)
;                      BP+6+8      BP+10      BP+12+14    BP+16+18
;
.MODEL LARGE ;Pointers size = 4 bytes
.DATA
    I       DW  ?
    J       DW  ?
    N       DW  ?
    Min     DW  ?
    TempI   DW  ?
    TempJ   DW  ?
    Counter DW  ?
    Two     DW  2
.CODE
.386
PUBLIC _getDiffMin
_getDiffMin PROC FAR
Start:
    PUSH BP ;Save BP's current value
    MOV BP,SP
    PUSH SI
    PUSH DI
    PUSH CX
    PUSH ES
    PUSH GS
    MOV CX,WORD PTR [BP+10] ;CX point to size (matrix of size*size)
    MOV SI,WORD PTR [BP+6] ;SI point to pointer in *mat[] (points to rows)
    MOV ES,WORD PTR [BP+8] ;Segment of *mat[]
    MOV DI,WORD PTR ES:[SI] ;DI point to value in *mat[] (points to columns, with first pointer on rows so gives value)
    MOV ES,WORD PTR ES:[SI+2] ;Segment of *mat[]
    MOV I,0 ;Rows index counter
    MOV J,0 ;Columns index counter
    MOV Counter,CX
    ADD Counter,CX ;Counter for loop
FirstGetN: ;Get number to check with all other numbers
    MOV AX,WORD PTR ES:[DI] ;AX has value which DI is pointing to
    MOV N,AX
FirstSubNumbers:
    ADD DI,2 ;Point to next column
    MOV AX,WORD PTR ES:[DI] ;AX has value one column ahead from N
    SUB AX,N
    CMP AX,0
    JG Continue1
    NEG AX ;Convert sub result to positive
Continue1:
    MOV Min,AX ;Save minimum difference in Min for loop with compare ahead
    MOV SI,WORD PTR [BP+12] ;SI point to *num1 (in case first check had the minimum difference)
    MOV GS,WORD PTR [BP+14] ;Segment of *num1
    MOV AX,N
    MOV GS:[SI],AX ;*num1 = N
    MOV SI,WORD PTR [BP+16] ;SI point to *num2
    MOV GS,WORD PTR [BP+18] ;Segment of *num2
    MOV AX,WORD PTR ES:[DI] ;AX = second number
    MOV GS:[SI],AX ;*num2 = second number
GetN:
    MOV SI,WORD PTR [BP+6] 
    MOV ES,WORD PTR [BP+8] 
    ADD SI,I ;Add needed row
    MOV DI,WORD PTR ES:[SI]
    MOV ES,WORD PTR ES:[SI+2]
    ADD DI,J ;Add needed column
    MOV AX,WORD PTR ES:[DI]
    MOV N,AX ;N contains number being checked with others
    MOV AX,I ;In order to move from N location forward (numbers before were checked during the loop)
    MOV TempI,AX
    MOV AX,J
    MOV TempJ,AX
    MOV AX,Counter
    CMP TempJ,AX ;Meaning it's in last column
    JE Fix
AddJ:
    ADD TempJ,2 ;Move to next column
    JMP SubNumbers
Fix:
    MOV TempJ,0 ;Back to first column
    ADD TempI,4 ;New row
SubNumbers:
    MOV SI,WORD PTR [BP+6] 
    MOV ES,WORD PTR [BP+8] 
    ADD SI,TempI
    MOV DI,WORD PTR ES:[SI]
    MOV ES,WORD PTR ES:[SI+2]
    ADD DI,TempJ
    MOV AX,WORD PTR ES:[DI] ;AX contains number to check with N
    MOV BX,N ;Move N to BX in order to save N's value
    SUB BX,AX ;BX (N) -= AX
    CMP BX,0
    JG Continue2
    Neg BX
Continue2:
    MOV AX,Min
    SUB AX,BX ;Substract former minimum and current sub result
    CMP AX,0 ;To check which one is bigger
    JLE Continue3 ;If BX > AX 
    MOV Min,BX ;Else, Min=BX
    MOV SI,WORD PTR [BP+12] ;SI point to *num1
    MOV GS,WORD PTR [BP+14] ;Segment of *num1
    MOV AX,N
    MOV GS:[SI],AX ;*num1 = N
    MOV SI,WORD PTR [BP+16] ;SI point to *num2
    MOV GS,WORD PTR [BP+18] ;Segment of *num2
    MOV AX,WORD PTR ES:[DI] ;AX = second number
    MOV GS:[SI],AX ;*num2 = second number
Continue3:
    MOV AX,Counter
    CMP TempJ,AX ;Meaning all columns were checked 
    JNE AddJ
    MOV TempJ,0 ;Else, go to first column
    ADD TempI,4 ;Next row
    MUL Two
    CMP TempI,AX ;Meaning all rows (and columns) were checked 
    JNE SubNumbers
    MOV AX,Counter
    ADD J,2 ;Move to next column with N number (J is pointing to INT so advance 2 bytes)
    CMP J,AX
    JNE GetN
Fix2:
    MOV J,0
    MOV AX,Counter
    MUL Two
    ADD I,4
    CMP I,AX ;If all rows have been checked with N number (I is pointing to pointer so jumps of 4 byte, LARGE MODEL)
    JE Finish
    JMP GetN
Finish:
    MOV AX,Min ;Save value to return
    POP GS ;POP by LIFO order
    POP ES
    POP CX 
    POP DI
    POP SI
    POP BP
    RET ;AX, IP and CS
_getDiffMin ENDP
END Start

Спасибо.

1 Ответ

0 голосов
/ 21 января 2019

Ответ - мне нужно было добавить 2 для «циклов», поскольку «размер» (взятый из кода C) начинает отсчет с 0.

Вот код ASM:

;extern int getDiffMin(int *mat[], int size , int *num1 , int *num2)
;                      BP+6+8      BP+10      BP+12+14    BP+16+18
;
.MODEL LARGE ;Pointers size = 4 bytes
.DATA
    I       DW  ?
    J       DW  ?
    N       DW  ?
    Min     DW  ?
    TempI   DW  ?
    TempJ   DW  ?
    Counter DW  ?
    Two     DW  2
.CODE
.386
PUBLIC _getDiffMin
_getDiffMin PROC FAR
Start:
    PUSH BP ;Save BP's current value
    MOV BP,SP
    PUSH SI
    PUSH DI
    PUSH CX
    PUSH ES
    PUSH GS
    MOV CX,WORD PTR [BP+10] ;CX point to size (matrix of size*size)
    MOV SI,WORD PTR [BP+6] ;SI point to pointer in *mat[] (points to rows)
    MOV ES,WORD PTR [BP+8] ;Segment of *mat[]
    MOV DI,WORD PTR ES:[SI] ;DI point to value in *mat[] (points to columns, with first pointer on rows so gives value)
    MOV ES,WORD PTR ES:[SI+2] ;Segment of *mat[]
    MOV I,0 ;Rows index counter
    MOV J,0 ;Columns index counter
    MOV Counter,CX
    ADD Counter,2 ;Since size starts from 0, need to make our "loop" bigger by 2
FirstGetN: ;Get number to check with all other numbers
    MOV AX,WORD PTR ES:[DI] ;AX has value which DI is pointing to
    MOV N,AX
FirstSubNumbers:
    ADD DI,2 ;Point to next column
    MOV AX,WORD PTR ES:[DI] ;AX has value one column ahead from N
    SUB AX,N
    CMP AX,0
    JG Continue1
    NEG AX ;Convert sub result to positive
Continue1:
    MOV Min,AX ;Save minimum difference in Min for loop with compare ahead
    MOV SI,WORD PTR [BP+12] ;SI point to *num1 (in case first check had the minimum difference)
    MOV GS,WORD PTR [BP+14] ;Segment of *num1
    MOV AX,N
    MOV GS:[SI],AX ;*num1 = N
    MOV SI,WORD PTR [BP+16] ;SI point to *num2
    MOV GS,WORD PTR [BP+18] ;Segment of *num2
    MOV AX,WORD PTR ES:[DI] ;AX = second number
    MOV GS:[SI],AX ;*num2 = second number
GetN:
    MOV SI,WORD PTR [BP+6] 
    MOV ES,WORD PTR [BP+8] 
    ADD SI,I ;Add needed row
    MOV DI,WORD PTR ES:[SI]
    MOV ES,WORD PTR ES:[SI+2]
    ADD DI,J ;Add needed column
    MOV AX,WORD PTR ES:[DI]
    MOV N,AX ;N contains number being checked with others
    MOV AX,I ;In order to move from N location forward (numbers before were checked during the loop)
    MOV TempI,AX
    MOV AX,J
    MOV TempJ,AX
    MOV AX,Counter
    CMP TempJ,AX ;Meaning it's in last column
    JE Fix
AddJ:
    ADD TempJ,2 ;Move to next column
    JMP SubNumbers
Fix:
    MOV TempJ,0 ;Back to first column
    ADD TempI,4 ;New row
SubNumbers:
    MOV SI,WORD PTR [BP+6] 
    MOV ES,WORD PTR [BP+8] 
    ADD SI,TempI
    MOV DI,WORD PTR ES:[SI]
    MOV ES,WORD PTR ES:[SI+2]
    ADD DI,TempJ
    MOV AX,WORD PTR ES:[DI] ;AX contains number to check with N
    MOV BX,N ;Move N to BX in order to save N's value
    SUB BX,AX ;BX (N) -= AX
    CMP BX,0
    JG Continue2
    Neg BX
Continue2:
    MOV AX,Min
    SUB AX,BX ;Substract former minimum and current sub result
    CMP AX,0 ;To check which one is bigger
    JLE Continue3 ;If BX > AX 
    MOV Min,BX ;Else, Min=BX
    MOV SI,WORD PTR [BP+12] ;SI point to *num1
    MOV GS,WORD PTR [BP+14] ;Segment of *num1
    MOV AX,N
    MOV GS:[SI],AX ;*num1 = N
    MOV SI,WORD PTR [BP+16] ;SI point to *num2
    MOV GS,WORD PTR [BP+18] ;Segment of *num2
    MOV AX,WORD PTR ES:[DI] ;AX = second number
    MOV GS:[SI],AX ;*num2 = second number
Continue3:
    MOV AX,Counter
    CMP TempJ,AX ;Meaning all columns were checked 
    JNE AddJ
    MOV TempJ,0 ;Else, go to first column
    ADD TempI,4 ;Next row
    MOV AX,Counter
    ADD AX,2
    MUL Two
    CMP TempI,AX ;Meaning all rows (and columns) were checked 
    JNE SubNumbers
    MOV AX,Counter
    ADD J,2 ;Move to next column with N number (J is pointing to INT so advance 2 bytes)
    CMP J,AX
    JNE GetN
Fix2:
    MOV J,0
    ADD I,4
    MOV AX,Counter
    ADD AX,2
    MUL Two
    CMP I,AX ;If all rows have been checked with N number (I is pointing to pointer so jumps of 4 byte, LARGE MODEL)
    JE Finish
    JMP GetN
Finish:
    MOV AX,Min ;Save value to return
    POP GS ;POP by LIFO order
    POP ES
    POP CX 
    POP DI
    POP SI
    POP BP
    RET ;AX, IP and CS
_getDiffMin ENDP
END Start
...