나는 어떤 종류의 어셈블리에서도 프로그래밍에 익숙하지 않다. 그리고 리눅스 용 NASM 타입 어셈블리가 DOS 기반 어셈블리에 비해 비교적 간단하다고 들었 기 때문에 나는 그것을 시도하기로 결정했다.Linux 어셈블리; 논쟁 목록이 나아 간다
이 내 프로그램은 지금까지입니다 :
section .data
opening: db 'Opening file...',10
openingLen: equ $-opening
opened: db 'File opened.',10
openedLen: equ $-opened
bad_params: db 'Usage: writeFile filename.ext',10
bad_paramsLen: equ $-bad_params
not_opened: db 'Unable to open file. Halted.',10
not_openedLen: equ $-not_opened
hello: db 'Hello, this is written to a file'
helloLen: equ $-hello
success: db 'Successfully wrote to file.',10
successLen: equ $-success
section .bss
file: resd 1
section .text
global _start:
_start:
pop ebx ; pop number of params
test ebx,2 ; make sure there are only 2
jne bad_param_list
pop ebx
mov eax,4 ; write out opening file msg
mov ebx,1
mov ecx,opening
mov edx,openingLen
int 80h
mov eax,5 ; open file
pop ebx
mov ecx,64
mov edx,777o ; permissions of file
int 80h
mov dword [file],eax
test dword [file],0
jle bad_open
mov eax,4 ; write successful open message
mov ebx,1
mov ecx,opened
mov edx,openedLen
int 80h
mov ebx,file ; write to file (4 already in eax)
mov ecx,hello
mov edx,helloLen
int 80h
mov eax,6 ; close file
mov ebx,file
int 80h
mov eax,4 ; write successfully written msg
mov ebx,1
mov ecx,success
mov edx,successLen
int 80h
mov eax,1 ; exit
mov ebx,0
int 80h
bad_param_list:
mov eax,4 ; write that params are bad
mov ebx,1
mov ecx,bad_params
mov edx,bad_paramsLen
int 80h
mov eax,1 ; exit with code 1
mov ebx,1
int 80h
bad_open:
mov eax,4 ; write that we couldn't open the file
mov ebx,1
mov ecx,not_opened
mov edx,not_openedLen
int 80h
mov eax,1 ; exit with code 2
mov ebx,2
int 80h
목표는 라이브러리 함수없이 파일에 텍스트 문자열을 작성하는 것입니다; 나는 리눅스 커널만을 사용하고있다. 저는 여기 저기에 괄호가 빠져있는 것에 약간의 문제가있었습니다, 그리고 여러분이 멍청한 놈들에게서 기대할 수있는 나머지 모든 실수들에 대해, 저는 이것이 현재 대부분 통제하에 있다고 생각합니다.
여기 내 문제가있다 :이 프로그램의 처음 네 줄은 스택에서 인수의 수를 띄우고, 하나의 매개 변수 (프로그램 이름 제외)가있을 경우 bad_param_list
으로 점프하고 pop 스택에서 프로그램 이름.
그러나 이것은 발생하지 않습니다. 여기에 I/O를 명확하게하기 위해 포맷 몇 가지 예제는 다음과 같습니다
$./writeFile
Opening file...
Unable to open file. Halted.
$./writeFile x
Usage: writeFile filename.ext
$./writeFile x x
Usage: writeFile filename.ext
$./writeFile x x x
Opening file...
Unable to open file. Halted.
$./writeFile x x x x
Opening file...
Unable to open file. Halted.
$./writeFile x x x x x
Usage: writeFile filename.ext
$./writeFile x x x x x x
Usage: writeFile filename.ext
내가 발견 한 것은 당신이 2로 프로그램의 이름, 나누기를 포함하여 인수의 수를 고려해야하고, 경우, 소수점을 무시하는 경우 대답은 이상합니다. 내 사용 오류가 발생하지만 답변이 짝수이면 오류를 열 수 없습니다. 이것은 적어도 10 개의 논쟁까지 사실입니다!
어떻게 이런 일을 할 수 있었습니까? 그리고 예상되는 결과를 얻으려면 어떻게해야합니까? 대신
test ebx,2
의
왜 모든 시작 어셈블리 프로그래머는 그들이 찾을 수있는 가장 뼈없는 인터페이스로 작동하는 완전한 프로그램을 작성하여 시작한다고 결정하는 것입니까? C 프로그램에 링크하고 I/O를 위해 기존의 C 런타임 라이브러리를 사용하는 어셈블러 함수를 작성하는 것이 훨씬 쉽고, 유용하며, 양도 할 수있는 기술입니다. 나는 저수준의 것을 마스터 링하는 것이 _useless_ (그것은 아니다)라고 말하지는 않지만, 그것은 좀 더 밀교적이고 전문화되어있다. 자신을 "초보자"라고 부르는 경우, 먼저 기본적인 것을하지 않고 덜 간단한 작업을 수행하십시오. –
내가 그 결정을 한 주요 이유는 다음과 같습니다. 나는 프로그래밍에있어서가 아니라 _assembly_에서 초보자이다. 나는 조립식을 배우고 싶다. 왜냐하면 나는 뼈의 수준에 무엇이 있는지 이해하는 데 관심이 있기 때문이다. 라이브러리를 사용하려면 C 또는 C++로 작성합니다. 편집 : 죄송합니다. 방금 깨달은 것이 조금 엉뚱한 것 같습니다. 그것은 내가 의도 한 바가 전혀 아닙니다. – Mrrvomun
문제는이 방법을 사용하면 Linux가 프로세스를 초기화하는 방법이나 시스템 콜 인수가 마샬링되는 방법에 대한 일반적으로 관련없는 세부 정보를 학습하면서 같은 시간에 어셈블리를 가르치려고하는 것을 끝낼 수 있다는 것입니다.어셈블리에 무언가를 쓸 이유가있는 가장 실질적인 경우에는 커널이나 응용 프로그램에서 C 코드로 인터페이스하는 것이 좋습니다. 반대로, 시스템 콜을 배우는 것은 _ 여러분이 libc 관리자가되기를 원할 때만 _ 가능할 것입니다. _Loringage_ 대신에 기존의 C 지식 _ignoring_ 그것! –