CMP и JGE не работают в Turbo C++

Я работаю над программой Mix на С++ и языке ассемблера (8086), чтобы найти наименьшее число из массива. Вот мой код

#include<iostream>
#include<conio.h>
using namespace std;
void main()
{
__int16 a[5],x,y,res;
int i,j;
y=999;

cout<<"\n Enter 5 Numbers:";
for(i=0;i<5;i++)
{
    cin>>a[i];
}

_asm{
    mov bx,y
}

//Finding smallest
for(i=0;i<5;i++)
{
    x=a[i];
    _asm{
        mov ax,x
        cmp ax,bx
        jge nxt
        mov bx,ax
        nxt:
    }
}

_asm{
    mov res,bx;
}

cout<<"\n Smallest Element:"<<res;
getch();
}

Приведенный выше код написан в Visual Studio 2010 и работает нормально. Но когда я обновляю тот же код для Turbo C++ (т. е. меняю «iostream» на «iostream.h», удаляю «используя пространство имен std;», меняю «__int16» на «int» и т. д.), он не работает. Ответ, полученный после выполнения, неверен.

Вот моя программа TC++ для того же

#include<iostream.h>
#include<conio.h>
void main()
{
int a[5],x,y,res;
int i,j;
y=999;

cout<<"\n Enter 5 Numbers:";
for(i=0;i<5;i++)
{
    cin>>a[i];
}

_asm{
    mov bx,y
}

//Finding smallest
for(i=0;i<5;i++)
{
    x=a[i];
    _asm{
        mov ax,x
        cmp ax,bx
        jge nxt
        mov bx,ax
    }
    nxt:
}

_asm{
    mov res,bx;
}

cout<<"\n Smallest Element:"<<res;
getch();
}

Почему TC++ и Visual Studio 10 не дают одинакового ответа?


person Ankur    schedule 29.03.2013    source источник
comment
Можете ли вы показать код, который не работает? Кажется, вы говорите, что это не тот код, который дает неверный ответ.   -  person Drew Dormann    schedule 29.03.2013
comment
Посмотрите на два исполняемых файла в дизассемблере, чтобы определить, какие различия в сгенерированном коде могут вызывать неверные результаты. Или еще лучше, пройдитесь по коду в отладчике.   -  person Michael    schedule 29.03.2013
comment
Если вы скомпилируете свою программу с включенной отладочной информацией и загрузите ее в Turbo Debugger (td.exe), вы сможете увидеть дизассемблирование main и то, как for(i=0;i<5;i++) разрушает встроенный ассемблерный код.   -  person Alexey Frunze    schedule 29.03.2013
comment
sites.google.com/site/pratiktambe/assemblyandc   -  person Shmil The Cat    schedule 29.03.2013


Ответы (1)


Нельзя ожидать, что регистры сохранят свои значения между фрагментами сборки. У вас есть три ассемблерных фрагмента с кусками C между ними, и они полагаются на то, что bx останется прежним. Компилятор не дает таких обещаний.

Либо используйте память для хранения текущего минимума, либо переформулируйте с помощью одного фрагмента сборки. Для последнего подхода вам придется переписать цикл for и доступ к массиву в сборке; это вполне выполнимо. Так:

_asm{
mov dx, y ; we'll use dx instead of bx for the running minimum - long story
mov bx, a   ; that's the array pointer
mov si, 0 ; that's our i
loop:
    mov ax, [bx+si*2] ; read a[i] into ax; *2 because int is two bytes
    cmp ax,dx
    jge nxt
    mov dx, ax
    nxt:
    ;Now the for loop stuff
    inc si ; i++
    cmp si, 5 ; compare i to 5
    jl loop   ; if less, continue looping
; End of loop
mov res,dx;
}

Я использую bx и si для доступа к памяти base+index, потому что на ранних процессорах x86 вы могли делать такой доступ к памяти только с ограниченным подмножеством регистров (bx или bp для base, si или di для index). В наши дни вы можете использовать любую комбинацию регистров; но я не уверен, что старинный Turbo C выдержит это.

person Seva Alekseyev    schedule 29.03.2013
comment
Спасибо. Регистры не сохраняли значения. - person Ankur; 29.03.2013