วิธีการเขียน hello world ในแอสเซมเบลอร์ภายใต้ Windows


94

ฉันต้องการเขียนสิ่งพื้นฐานในการประกอบใน Windows ฉันใช้ NASM แต่ฉันไม่สามารถทำงานอะไรได้เลย

จะเขียนและรวบรวมสวัสดีชาวโลกโดยไม่ใช้ฟังก์ชัน C บน Windows ได้อย่างไร?


3
ตรวจสอบชุดประกอบ Windows Small Is Beautifulของ Steve Gibson ด้วย
Jeremy

การไม่ใช้ c-libraries เป็นข้อ จำกัด ที่ค่อนข้างแปลก เราต้องเรียกไลบรารีบางส่วนภายในระบบปฏิบัติการ MS-Windows อาจเป็น kernel32.dll ไม่ว่า Microsoft จะเขียนสิ่งนี้ใน c หรือ Pascal ดูเหมือนจะไม่เกี่ยวข้อง หมายความว่าสามารถเรียกใช้ฟังก์ชันที่มาจาก OS ได้เท่านั้นสิ่งใดในระบบ Unix จะเรียกว่าการเรียกระบบ
Albert van der Horst

ด้วยไลบรารี C ฉันถือว่าเขาหมายถึงโดยไม่ใช้ไลบรารีรันไทม์ C เหมือนกับไลบรารีที่มาพร้อมกับ GCC หรือ MSVC แน่นอนเขาหรือเธอจะต้องใช้ Windows DLL มาตรฐานบางอย่างเช่น kernel32.dll
Rudy Velthuis

2
ความแตกต่างระหว่าง kernel32.dll และไลบรารีรันไทม์ gcc ไม่อยู่ในรูปแบบ (ทั้งสองเป็น dll) และไม่อยู่ในภาษา (ทั้งสองอย่างอาจเป็น c แต่จะถูกซ่อนไว้) ความแตกต่างระหว่าง OS ที่จัดหาหรือไม่
Albert van der Horst

ฉันมองหาสิ่งนี้ด้วยฮ่า ๆ ไม่พบสิ่งใดที่มี fasm โดยไม่รวม
bluejayke

คำตอบ:


39

ตัวอย่าง NASM

เรียก libc stdio printfการใช้งานint main(){ return printf(message); }

; ----------------------------------------------------------------------------
; helloworld.asm
;
; This is a Win32 console program that writes "Hello, World" on one line and
; then exits.  It needs to be linked with a C library.
; ----------------------------------------------------------------------------

    global  _main
    extern  _printf

    section .text
_main:
    push    message
    call    _printf
    add     esp, 4
    ret
message:
    db  'Hello, World', 10, 0

จากนั้นเรียกใช้

nasm -fwin32 helloworld.asm
gcc helloworld.obj
a

นอกจากนี้ยังมีThe Clueless Newbies Guide to Hello World in Nasmโดยไม่ต้องใช้ไลบรารี C จากนั้นโค้ดจะมีลักษณะดังนี้

รหัส 16 บิตกับ MS-DOS สายระบบ: ผลงานในการเลียนแบบ DOS หรือใน Windows 32 บิตด้วยการสนับสนุน ไม่สามารถเรียกใช้ "โดยตรง" (โปร่งใส) ภายใต้ Windows 64 บิตใด ๆ เนื่องจากเคอร์เนล x86-64 ไม่สามารถใช้โหมด vm86

org 100h
mov dx,msg
mov ah,9
int 21h
mov ah,4Ch
int 21h
msg db 'Hello, World!',0Dh,0Ah,'$'

สร้างสิ่งนี้ให้เป็น.comไฟล์ปฏิบัติการดังนั้นจะถูกโหลดcs:100hพร้อมกับการลงทะเบียนทุกส่วนที่เท่าเทียมกัน (แบบจำลองหน่วยความจำขนาดเล็ก)

โชคดี.


28
คำถามกล่าวถึง "โดยไม่ใช้ไลบรารี C" อย่างชัดเจน
Mehrdad Afshari

25
ไม่ถูกต้อง. เห็นได้ชัดว่าไลบรารี C สามารถทำได้ดังนั้นจึงเป็นไปได้ ในความเป็นจริงมันยากกว่าเล็กน้อยเท่านั้น คุณต้องเรียก WriteConsole () ด้วยพารามิเตอร์ 5 ตัวที่ถูกต้อง
MSalters

12
แม้ว่าตัวอย่างที่สองจะไม่เรียกใช้ฟังก์ชันไลบรารี C แต่ก็ไม่ใช่โปรแกรม Windows เช่นกัน Virtual DOS Machine จะถูกยิงเพื่อเรียกใช้งาน
Rômulo Ceccon

7
@ Alex Hart ตัวอย่างที่สองของเขาคือ DOS ไม่ใช่สำหรับ Windows ใน DOS โปรแกรมในโหมดเล็ก ๆ (ไฟล์. COM ภายใต้รหัสรวม 64Kb + data + stack) เริ่มต้นที่ 0x100h เนื่องจาก 256 ไบต์แรกในเซ็กเมนต์นั้นถูกยึดโดย PSP (อาร์เรย์บรรทัดคำสั่งเป็นต้น) ดูลิงค์นี้: en.wikipedia.org/wiki/Program_Segment_Prefix
zvolkov

7
นี่ไม่ใช่สิ่งที่ถูกขอ ตัวอย่างแรกใช้ไลบรารี C และอันที่สองคือ MS-DOS ไม่ใช่ Windows
Paulo Pinto

131

ตัวอย่างนี้แสดงวิธีไปที่ Windows API โดยตรงและไม่เชื่อมโยงใน C Standard Library

    global _main
    extern  _GetStdHandle@4
    extern  _WriteFile@20
    extern  _ExitProcess@4

    section .text
_main:
    ; DWORD  bytes;    
    mov     ebp, esp
    sub     esp, 4

    ; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
    push    -11
    call    _GetStdHandle@4
    mov     ebx, eax    

    ; WriteFile( hstdOut, message, length(message), &bytes, 0);
    push    0
    lea     eax, [ebp-4]
    push    eax
    push    (message_end - message)
    push    message
    push    ebx
    call    _WriteFile@20

    ; ExitProcess(0)
    push    0
    call    _ExitProcess@4

    ; never here
    hlt
message:
    db      'Hello, World', 10
message_end:

ในการคอมไพล์คุณจะต้องมี NASM และ LINK.EXE (จาก Visual studio Standard Edition)

   nasm -fwin32 สวัสดีครับ
   ลิงค์ / ระบบย่อย: console / nodefaultlib / entry: main hello.obj 

21
คุณอาจต้องรวม kernel32.lib เพื่อเชื่อมโยงสิ่งนี้ (ฉันทำ) link / subsystem: console / nodefaultlib / entry: main hello.obj kernel32.lib
Zach Burlingame

5
จะเชื่อมโยง obj กับ ld.exe จาก MinGW ได้อย่างไร
DarrenVortex

4
@DarrenVortexgcc hello.obj
Towry

4
สิ่งนี้จะใช้งานได้โดยใช้ตัวเชื่อมโยงฟรีเช่น Alink จากsourceforge.net/projects/alinkหรือ GoLink จากgodevtool.com/#linkerหรือไม่ ฉันไม่ต้องการติดตั้ง Visual Studio เพื่อสิ่งนั้นเท่านั้น?
jj_

21

นี่คือตัวอย่าง Win32 และ Win64 โดยใช้การเรียก Windows API พวกเขามีไว้สำหรับ MASM มากกว่า NASM แต่ลองดูที่พวกเขา คุณสามารถค้นหารายละเอียดเพิ่มเติมในนี้บทความ

สิ่งนี้ใช้ MessageBox แทนการพิมพ์ไปยัง stdout

Win32 MASM

;---ASM Hello World Win32 MessageBox

.386
.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib

.data
title db 'Win32', 0
msg db 'Hello World', 0

.code

Main:
push 0            ; uType = MB_OK
push offset title ; LPCSTR lpCaption
push offset msg   ; LPCSTR lpText
push 0            ; hWnd = HWND_DESKTOP
call MessageBoxA
push eax          ; uExitCode = MessageBox(...)
call ExitProcess

End Main

Win64 หน้ากาก

;---ASM Hello World Win64 MessageBox

extrn MessageBoxA: PROC
extrn ExitProcess: PROC

.data
title db 'Win64', 0
msg db 'Hello World!', 0

.code
main proc
  sub rsp, 28h  
  mov rcx, 0       ; hWnd = HWND_DESKTOP
  lea rdx, msg     ; LPCSTR lpText
  lea r8,  title   ; LPCSTR lpCaption
  mov r9d, 0       ; uType = MB_OK
  call MessageBoxA
  add rsp, 28h  
  mov ecx, eax     ; uExitCode = MessageBox(...)
  call ExitProcess
main endp

End

ในการประกอบและเชื่อมโยงสิ่งเหล่านี้โดยใช้ MASM ให้ใช้สิ่งนี้สำหรับปฏิบัติการ 32 บิต:

ml.exe [filename] /link /subsystem:windows 
/defaultlib:kernel32.lib /defaultlib:user32.lib /entry:Main

หรือสิ่งนี้สำหรับปฏิบัติการ 64 บิต:

ml64.exe [filename] /link /subsystem:windows 
/defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main

เหตุใด x64 Windows จึงต้องจองพื้นที่สแต็ก 28 ชม. ก่อน a call? นั่นคือพื้นที่เงา 32 ไบต์ (0x20) หรือที่เรียกว่าพื้นที่บ้านตามที่กำหนดไว้ในรูปแบบการเรียก และอีก 8 ไบต์ใหม่จัดสแต็ค 16 เพราะการประชุมเรียกร้องต้องถูก RSP 16 ไบต์ชิดก่อน call( mainผู้โทรของเรา(ในรหัสเริ่มต้น CRT) ทำเช่นนั้นที่อยู่ส่งคืน 8 ไบต์หมายความว่า RSP อยู่ห่างจากขอบเขต 16 ไบต์ 8 ไบต์เมื่อเข้าสู่ฟังก์ชัน)

พื้นที่เงาสามารถใช้โดยฟังก์ชันเพื่อดัมพ์อาร์เรย์รีจิสเตอร์ที่อยู่ถัดจากตำแหน่งที่สแต็กอาร์ก (ถ้ามี) จะอยู่ A system callต้องการ 30 ชม. (48 ไบต์) เพื่อสำรองพื้นที่สำหรับ r10 และ r11 นอกเหนือจากการลงทะเบียน 4 รายการที่กล่าวถึงก่อนหน้านี้ แต่การเรียก DLL เป็นเพียงการเรียกใช้ฟังก์ชันแม้ว่าจะเป็นการเรียกใช้syscallคำสั่งก็ตาม

ข้อเท็จจริงที่น่าสนใจ: ไม่ใช่ Windows เช่นการเรียกใช้ x86-64 System V (เช่นบน Linux) ไม่ได้ใช้พื้นที่เงาเลยและใช้อาร์เรย์รีจิสเตอร์จำนวนเต็ม / ตัวชี้ได้สูงสุด 6 รายการและอาร์เรย์ FP สูงสุด 8 รายการในการลงทะเบียน XMM .


การใช้invokeคำสั่งของ MASM (ซึ่งรู้หลักการเรียก) คุณสามารถใช้ ifdef หนึ่งรายการเพื่อสร้างเวอร์ชันนี้ซึ่งสามารถสร้างเป็น 32 บิตหรือ 64 บิต

ifdef rax
    extrn MessageBoxA: PROC
    extrn ExitProcess: PROC
else
    .386
    .model flat, stdcall
    include kernel32.inc
    includelib kernel32.lib
    include user32.inc
    includelib user32.lib
endif
.data
caption db 'WinAPI', 0
text    db 'Hello World', 0
.code
main proc
    invoke MessageBoxA, 0, offset text, offset caption, 0
    invoke ExitProcess, eax
main endp
end

ตัวแปรมาโครเหมือนกันสำหรับทั้งคู่ แต่คุณจะไม่ได้เรียนรู้การประกอบด้วยวิธีนี้ คุณจะได้เรียนรู้ asm สไตล์ C แทน invokeสำหรับstdcallหรือfastcallในขณะที่cinvokeสำหรับการหรืออาร์กิวเมนต์ตัวแปรcdecl fastcallแอสเซมเบลอร์รู้ว่าต้องใช้อะไร

คุณสามารถแยกชิ้นส่วนเอาต์พุตเพื่อดูว่าinvokeขยายได้อย่างไร


1
+1 สำหรับคำตอบของคุณ คุณช่วยเพิ่มรหัสประกอบสำหรับ Windows บน ARM (WOA) ด้วยได้ไหม
Annie

1
เหตุใด rsp จึงต้องการ 0x28 ไบต์และไม่ใช่ 0x20 การอ้างอิงทั้งหมดในการประชุมเรียกว่าควรเป็น 32 แต่ดูเหมือนว่าจะต้องใช้ 40 ในทางปฏิบัติ
douggard

ในรหัสกล่องข้อความ 32 บิตของคุณด้วยเหตุผลบางประการเมื่อฉันใช้titleเป็นชื่อป้ายกำกับฉันพบข้อผิดพลาด อย่างไรก็ตามเมื่อฉันใช้อย่างอื่นเป็นชื่อป้ายกำกับmytitleทุกอย่างก็ใช้ได้ดี
user3405291

วิธีทำ withoiut รวมถึง?
bluejayke

13

Flat Assemblerไม่จำเป็นต้องมีตัวเชื่อมพิเศษ ทำให้การเขียนโปรแกรมแอสเซมเบลอร์ทำได้ง่ายมาก นอกจากนี้ยังสามารถใช้ได้กับ Linux

นี่hello.asmมาจากตัวอย่าง Fasm:

include 'win32ax.inc'

.code

  start:
    invoke  MessageBox,HWND_DESKTOP,"Hi! I'm the example program!",invoke GetCommandLine,MB_OK
    invoke  ExitProcess,0

.end start

Fasm สร้างไฟล์ปฏิบัติการ:

> fasm สวัสดีครับ
แอสเซมเบลอร์แบบแบนเวอร์ชัน 1.70.03 (หน่วยความจำ 1048575 กิโลไบต์)
4 รอบ 1536 ไบต์

และนี่คือโปรแกรมในIDA :

ป้อนคำอธิบายภาพที่นี่

ท่านสามารถเข้าดูสามโทร: GetCommandLine, และMessageBoxExitProcess


สิ่งนี้ใช้การรวมและ GUI เราจะทำอย่างไรกับ CMD โดยไม่รวมเลย?
bluejayke

พยายามอ่านคู่มือหรือไม่? flatassembler.net/docs.php?article=manual#2.4.2
สิ้นสุด

คุณช่วยชี้ฉันไปยังส่วนที่เขียนลงในคอนโซลโดยไม่มี dlls ได้ไหม
bluejayke

12

ในการรับ. exe ด้วย NASM'compiler และตัวเชื่อมโยงของ Visual Studio รหัสนี้ใช้ได้ดี:

global WinMain
extern ExitProcess  ; external functions in system libraries 
extern MessageBoxA

section .data 
title:  db 'Win64', 0
msg:    db 'Hello world!', 0

section .text
WinMain:
    sub rsp, 28h  
    mov rcx, 0       ; hWnd = HWND_DESKTOP
    lea rdx,[msg]    ; LPCSTR lpText
    lea r8,[title]   ; LPCSTR lpCaption
    mov r9d, 0       ; uType = MB_OK
    call MessageBoxA
    add rsp, 28h  

    mov  ecx,eax
    call ExitProcess

    hlt     ; never here

หากรหัสนี้ถูกบันทึกในเช่น "test64.asm" ดังนั้นในการคอมไพล์:

nasm -f win64 test64.asm

สร้าง "test64.obj" จากนั้นเพื่อเชื่อมโยงจากพรอมต์คำสั่ง:

path_to_link\link.exe test64.obj /subsystem:windows /entry:WinMain  /libpath:path_to_libs /nodefaultlib kernel32.lib user32.lib /largeaddressaware:no

โดยที่path_to_linkอาจเป็นC: \ Program Files (x86) \ Microsoft Visual Studio 10.0 \ VC \ binหรือที่ใดก็ตามที่เป็นโปรแกรม link.exe ของคุณในเครื่องของคุณ path_to_libsอาจเป็นC: \ Program Files (x86) \ Windows Kits \ 8.1 \ Lib \ winv6.3 \ um \ x64หรือที่ใดก็ตามที่ไลบรารีของคุณ (ในกรณีนี้ทั้ง kernel32.lib และ user32.lib อยู่ในที่เดียวกันมิฉะนั้นให้ใช้หนึ่งตัวเลือกสำหรับแต่ละเส้นทางที่คุณต้องการ) และ/ largeaddressaware: ไม่มีตัวเลือกคือ จำเป็นเพื่อหลีกเลี่ยงการบ่นของผู้เชื่อมโยงเกี่ยวกับที่อยู่ที่ยาว (สำหรับ user32.lib ในกรณีนี้) นอกจากนี้เมื่อทำเสร็จแล้วที่นี่หากตัวเชื่อมโยงของ Visual ถูกเรียกใช้จากพรอมต์คำสั่งจำเป็นต้องตั้งค่าสภาพแวดล้อมก่อนหน้านี้ (เรียกใช้ครั้งเดียว vcvarsall.bat และ / หรือดูMS C ++ 2010 และ mspdb100.dll).


2
ฉันขอแนะนำอย่างยิ่งให้ใช้default relที่ด้านบนสุดของไฟล์ของคุณดังนั้นโหมดการกำหนดแอดเดรสเหล่านั้น ( [msg]และ[title]) ใช้การกำหนดแอดเดรสแบบสัมพันธ์ RIP แทนค่าสัมบูรณ์ 32 บิต
Peter Cordes

ขอบคุณที่อธิบายวิธีการเชื่อมโยง! คุณช่วยสุขภาพจิตของฉัน ฉันเริ่มดึงผมออกจาก 'ข้อผิดพลาด LNK2001: สัญลักษณ์ภายนอกที่ไม่ได้รับการแก้ไข ExitProcess' และข้อผิดพลาดที่คล้ายกัน ...
Nik

5

เว้นแต่คุณจะเรียกใช้ฟังก์ชันบางอย่างสิ่งนี้ก็ไม่สำคัญเลย (และอย่างจริงจังไม่มีความแตกต่างอย่างแท้จริงในความซับซ้อนระหว่างการเรียก printf และการเรียกใช้ฟังก์ชัน win32 api)

แม้แต่ DOS int 21h ก็เป็นเพียงการเรียกใช้ฟังก์ชันแม้ว่าจะเป็น API อื่นก็ตาม

หากคุณต้องการทำโดยไม่ได้รับความช่วยเหลือคุณจำเป็นต้องพูดคุยกับฮาร์ดแวร์วิดีโอของคุณโดยตรงให้เขียนบิตแมปของตัวอักษร "Hello world" ลงในเฟรมบัฟเฟอร์ ถึงแม้การ์ดแสดงผลจะทำงานในการแปลค่าหน่วยความจำเหล่านั้นเป็นสัญญาณ VGA / DVI

โปรดทราบว่าจริงๆแล้วไม่มีสิ่งใดเลยที่ลงไปถึงฮาร์ดแวร์ใน ASM จะน่าสนใจไปกว่าในโปรแกรม C. A "hello world" ที่เรียกใช้ฟังก์ชัน สิ่งที่ดีอย่างหนึ่งเกี่ยวกับ ASM คือคุณสามารถใช้ ABI ใดก็ได้ที่คุณต้องการค่อนข้างง่าย คุณแค่ต้องรู้ว่า ABI คืออะไร


นี่เป็นจุดที่ยอดเยี่ยม --- ASM และ C ทั้งคู่อาศัยฟังก์ชั่นที่ OS ให้มา (_WriteFile ใน Windows) แล้วเวทมนตร์อยู่ที่ไหน? อยู่ในรหัสไดรเวอร์อุปกรณ์สำหรับการ์ดแสดงผล
Assad Ebrahim

2
นี้อย่างละเอียดนอกจากประเด็น ผู้โพสต์ถามโปรแกรมแอสเซมเบลอร์ที่รัน "ภายใต้ Windows" นั่นหมายความว่าสามารถใช้สิ่งอำนวยความสะดวกของ Windows ได้ (เช่น kernel32.dll) แต่ไม่ใช่สิ่งอำนวยความสะดวกอื่น ๆ เช่น libc ภายใต้ Cygwin สำหรับการร้องไห้ดัง ๆ ผู้โพสต์บอกอย่างชัดเจนว่าไม่มี c-libraries
Albert van der Horst

5

ตัวอย่างที่ดีที่สุดคือตัวอย่างที่มี fasm เนื่องจาก fasm ไม่ใช้ตัวเชื่อมโยงซึ่งซ่อนความซับซ้อนของการเขียนโปรแกรม windows ด้วยความซับซ้อนที่ทึบแสงอื่น หากคุณพอใจกับโปรแกรมที่เขียนลงในหน้าต่าง gui มีตัวอย่างสำหรับสิ่งนั้นในไดเร็กทอรีตัวอย่างของ fasm

หากคุณต้องการโปรแกรมคอนโซลที่ช่วยให้สามารถเปลี่ยนเส้นทางของมาตรฐานในและมาตรฐานออกที่เป็นไปได้ มีโปรแกรมตัวอย่าง (helas สูงไม่สำคัญ) ที่ไม่ใช้ gui และทำงานร่วมกับคอนโซลได้อย่างเคร่งครัดนั่นคือ fasm เอง สิ่งนี้สามารถทำให้บางลงได้ตามความจำเป็น (ฉันได้เขียนคอมไพเลอร์ที่สี่ซึ่งเป็นอีกตัวอย่างที่ไม่ใช่ gui แต่ก็ไม่สำคัญเช่นกัน)

โปรแกรมดังกล่าวมีคำสั่งต่อไปนี้เพื่อสร้างส่วนหัวที่เหมาะสมสำหรับปฏิบัติการ 32 บิตโดยปกติแล้วตัวเชื่อมโยง

FORMAT PE CONSOLE 

ส่วนที่เรียกว่า ".idata" มีตารางที่ช่วยให้หน้าต่างในระหว่างการเริ่มต้นใช้งานชื่อฟังก์ชันสองชื่อไปยังที่อยู่รันไทม์ นอกจากนี้ยังมีการอ้างอิงถึง KERNEL.DLL ซึ่งเป็นระบบปฏิบัติการ Windows

 section '.idata' import data readable writeable
    dd 0,0,0,rva kernel_name,rva kernel_table
    dd 0,0,0,0,0

  kernel_table:
    _ExitProcess@4    DD rva _ExitProcess
    CreateFile        DD rva _CreateFileA
        ...
        ...
    _GetStdHandle@4   DD rva _GetStdHandle
                      DD 0

รูปแบบตารางถูกกำหนดโดย windows และมีชื่อที่ค้นหาในไฟล์ระบบเมื่อโปรแกรมเริ่มทำงาน FASM ซ่อนความซับซ้อนบางอย่างไว้เบื้องหลังคีย์เวิร์ด rva ดังนั้น _ExitProcess @ 4 จึงเป็น fasm label และ _exitProcess คือสตริงที่ Windows ค้นหา

โปรแกรมของคุณอยู่ในส่วน ".text" หากคุณประกาศว่าส่วนนั้นอ่านเขียนได้และปฏิบัติการได้นั่นเป็นส่วนเดียวที่คุณต้องเพิ่ม

    section '.text' code executable readable writable

คุณสามารถเรียกสิ่งอำนวยความสะดวกทั้งหมดที่คุณประกาศไว้ในส่วน. idata สำหรับโปรแกรมคอนโซลคุณต้องมี _GetStdHandle เพื่อค้นหา filedescriptors สำหรับ standard in และ standardout (ใช้ชื่อสัญลักษณ์เช่น STD_INPUT_HANDLE ซึ่ง fasm พบในไฟล์ include win32a.inc) เมื่อคุณมีตัวอธิบายไฟล์แล้วคุณสามารถเขียน WriteFile และ ReadFile ได้ ฟังก์ชันทั้งหมดอธิบายไว้ในเอกสาร kernel32 คุณอาจจะทราบหรือไม่ลองเขียนโปรแกรมแอสเซมเบลอร์

โดยสรุป: มีตารางที่มีชื่อ asci ที่คู่กับ windows OS ในระหว่างการเริ่มต้นสิ่งนี้จะเปลี่ยนเป็นตารางที่อยู่ที่สามารถเรียกใช้ได้ซึ่งคุณใช้ในโปรแกรมของคุณ


FASM อาจไม่ใช้ตัวเชื่อมโยง แต่ยังต้องประกอบไฟล์ PE ซึ่งหมายความว่าจริงๆแล้วมันไม่ได้เป็นเพียงแค่การรวบรวมโค้ด แต่ยังรับงานตามปกติที่ตัวเชื่อมโยงจะทำงานและด้วยเหตุนี้ในความเห็นที่ต่ำต้อยของฉันจึงทำให้เข้าใจผิดว่าไม่มีตัวเชื่อมโยงว่า "ซ่อนความซับซ้อน" ค่อนข้างตรงกันข้าม - งานแอสเซมเบลอร์คือการประกอบโปรแกรม แต่ปล่อยให้ลิงค์เกอร์ฝังโปรแกรมลงในอิมเมจโปรแกรมซึ่งอาจขึ้นอยู่กับหลายสิ่งหลายอย่าง ด้วยเหตุนี้ฉันจึงพบว่าการแยกระหว่างตัวเชื่อมและแอสเซมเบลอร์เป็นสิ่งที่ดีซึ่งดูเหมือนว่าคุณไม่เห็นด้วย
AMN

@amn คิดถึงวิธีนี้ หากคุณใช้ตัวเชื่อมโยงเพื่อสร้างโปรแกรมข้างต้นจะช่วยให้คุณมีความเข้าใจมากขึ้นในสิ่งที่โปรแกรมทำหรือประกอบด้วยอะไรบ้าง? ถ้าฉันดูที่แหล่ง fasm ฉันรู้โครงสร้างทั้งหมดของโปรแกรม
Albert van der Horst

จุดยุติธรรม ในทางกลับกันการแยกการเชื่อมโยงออกจากสิ่งอื่น ๆ ก็มีประโยชน์เช่นกัน โดยปกติคุณสามารถเข้าถึงไฟล์ออบเจ็กต์ได้ (ซึ่งจะช่วยให้คนหนึ่งตรวจสอบโครงสร้างของโปรแกรมได้มากเกินไปโดยไม่ขึ้นกับรูปแบบไฟล์ภาพโปรแกรม) คุณสามารถเรียกใช้ตัวเชื่อมโยงที่แตกต่างกันตามความต้องการของคุณโดยมีตัวเลือกต่างๆ มันเกี่ยวกับการใช้ซ้ำและความสามารถในการประกอบ ด้วยเหตุนี้ FASM จึงทำทุกอย่างเพราะ "สะดวก" จึงทำลายหลักการเหล่านั้น ฉันไม่ได้ต่อต้านมันเป็นหลัก - ฉันเห็นเหตุผลของพวกเขาสำหรับมัน - แต่ฉันไม่ต้องการมัน
AMN

ได้รับข้อผิดพลาดสำหรับ isntruction ที่ผิดกฎหมายที่บรรทัดบนสุดในหน้าต่าง fasm 64 บิต
bluejayke

@bluejayke คุณอาจไม่มีเอกสารสำหรับ fasm ในมือ FORMAT PE สร้างไฟล์ปฏิบัติการ 32 บิตซึ่งหน้าต่าง 64 บิตไม่ยอมทำงาน สำหรับโปรแกรม 64 บิตคุณต้องการ FORMAT PE64 ตรวจสอบให้แน่ใจว่าคุณใช้คำแนะนำ 64 บิตที่ถูกต้องในโปรแกรมของคุณ
Albert van der Horst

3

หากคุณต้องการใช้ตัวเชื่อมโยง (link.exe) ของ NASM และ Visual Studio กับตัวอย่าง Hello World ของ anderstornvig คุณจะต้องเชื่อมโยงกับ C Runtime Libary ที่มีฟังก์ชัน printf () ด้วยตนเอง

nasm -fwin32 helloworld.asm
link.exe helloworld.obj libcmt.lib

หวังว่านี่จะช่วยใครบางคนได้


ผู้โพสต์คำถามต้องการทราบว่าใครบางคนจะเขียน printf ตามสิ่งอำนวยความสะดวกที่ Windows ให้มาได้อย่างไรนี่จึงเป็นอีกครั้งที่นอกเหนือจากประเด็น
Albert van der Horst
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.