[asm + c] problem ze scanf

0

Mam problem z użyciem w ASM funkcji sncan ktora by wczytała od użytkownika 2 zmienne naraz. Uda się tylko do 1, a w drugiej się pojawiają jakieś śmieci. Może ktoś mógłby pomóc :) :

segment .data
  wypisz_znak	db "%c", 0x0
  wypisz_liczby	db "Podales(x,y): (%d , %d)", 0x0
  wiad1	db "Podaj  (x, y) pierwszego punktu: ", 0Ah,0Dh, 0x0

  x_p2	dw 0
  y_p2	dw 0
  x_p3	db "%2d , %2d", 0

section .text
  extern printf
  extern scanf
  global main
	

main:
	push ebp
	mov ebp,esp

	sub esp, 40
	and esp, ~0x0f

	push wiad1		; Prosba o podanie x, y
	call printf		;
	pop eax			;
	
	lea	eax,[y_p2]	; Wpisanie do y_p2 liczby
	push	eax		;
	lea	eax,[x_p2]
	push	eax
	push	x_p3		;
	call	scanf		;
	add	esp,24		;

	mov	eax, [y_p2]	; Wypisanie podanej liczby
	push	eax		;
	mov	eax, [x_p2]	;
	push	eax		;
	push	wypisz_liczby	;
	call	printf		;
	add	esp,24		;

	mov esp, ebp
	pop ebp
	mov eax, 0
	ret
0
  1. Czytasz do shorta, użyj %hd.
  2. A po co te lea? Stałą, jaką jest niewątpliwie adres zmiennej, można pushnąć bezpośrednio (push x_p2 itp.). To samo z mov eax, [zmienna] push eax, można po prostu push dword [zmienna]. I klasyczny wręcz przykład, jak nie zerować rejestru - do tego jest xor albo sub. Przez takie kwiatki potem się mówi, że kompilatory generują lepszy kod niż pisany ręcznie :P.
0
manfredek napisał(a)

I klasyczny wręcz przykład, jak nie zerować rejestru - do tego jest xor albo sub. Przez takie kwiatki potem się mówi, że kompilatory generują lepszy kod niż pisany ręcznie :P.

Aaa zależy od procesora, na pentium4 mov jest najszybszy.
A czy na najnowszych (core) też? Nie mam pojęcia, warto by zrobić test.
Argumentem za mov jest:

  • brak zależności od innych instrukcji/rejestrów
  • jeśli procesor ma to wbudowane, jest to łatwiejsze do rozpoznania
    Przeciw:
  • 0 zajmuje aż 4 bajty, cała instrukcja 5, xor/sub zajmuje 2
  • wczytanie imm może dołożyć dodatkową robotę

Najszybsze będzie chyba mov reg, reg2, gdzie ten ostatni nie był ruszany dawno...
P.S. Kompilatory generują lepszy kod niż ręczny... najlepszy ręczny kod jest zazwyczaj równy temu z kompilatora, a i to trzeba być ekspertem...
Ręczny FPU już trochę lepiej, może dać aż 3% więcej :D
A w SSE (wszystko jedno którym) jak na razie rzeczywiście wygrywa człowiek.

0

Jak to się mówi - it depends. Ludzie i kompilatory zwykle walą xor. A pentium 4 to ma wiele swoich dziwactw...
Ten tekst o ręcznie pisanym kodzie to był taki dżołk, IMO nawet to zaznaczyłem...

0
manfredek napisał(a)
  1. Czytasz do shorta, użyj %hd.

nie rozumiem, próbowałem znaleźć co to jest to %hd ale oporowo idzie :(

0

h to modyfikator formatu scanf/printf, który oznacza short coś. W twoim przypadku d, czyli short int - a zmienne, do których czytasz to dw, czyli są shortami.
Hm, trochę się tym pobawiłem, ciągle działać nie chciało, ale już się uporałem... Kod jak zwykle pisany na szybko, niewydajny i ogólnie brzydki (na bank da się lepiej), ale masz: http://pastebin.4programmers.net/269

0

aaaa, to o scnaf'a chodziło, ok faktycznie działa jak należy.

To może przy okazji żeby nowego topica nie zakładać:
takie działa:

      a times 2500 db "O"
      (...)
	mov	eax,[y_p2]
	imul	eax,eax,50
	mov	byte[a + (eax + 6)*1 ], "S"

a takie nie ( error: invalid effective address w linii z zapisywaniem literki S ):

      a times 2500 db "O"
      (...)
	mov	eax,[y_p2]
	mov	byte[a + (eax*50 + 6)*1 ], "S"

Dodam że jesli się mnoży przez np. 9 to jest ok :P

0

Można mnożyć przez 1, 2, 3 (rej + rej * 2), 4, 5 (rej + rej * 4), 8, 9 (rej + rej * 8). Tylko.

1 użytkowników online, w tym zalogowanych: 0, gości: 1