Reputation: 3425
I have the following assembly code (NASM)
global _main
extern _sizeof
extern _printf
extern _objc_msgSend
extern _objc_getClass
extern _sel_registerName
SECTION .data
alert_text : db "NSAlert", 0
alloc_sel : db "alloc", 0
init_sel : dw "init", 0
alert_class: resb 4
SECTION .text
_main:
; get the class
sub esp, 8
push alert_text
call _objc_getClass
add esp, 12
; save class
mov dword [alert_class], eax
; get alloc selector
sub esp, 8
push alloc_sel
call _sel_registerName
add esp, 12
; allocate it
sub esp, 4
push alloc_sel
; push alert class
mov eax, dword [alert_class]
push eax
call _objc_msgSend
add esp, 12
mov eax, 0
ret
I then assemble it with
$ nasm -fmacho UI.asm -o UI.o
UI.asm:83: warning: uninitialised space declared in __data section: zeroing
$ ld UI.o -macosx_version_min 10.8 -lSystem -framework CoreFoundation -framework AppKit -o UI
When I run it I get
$ ./UI
2013-09-28 22:29:31.110 UI[60688:707] *** NSForwarding: warning: selector (0x201c) for message 'alloc' does not match selector known to Objective C runtime (0x97ee8e93)-- abort
2013-09-28 22:29:31.112 UI[60688:707] +[NSAlert alloc]: unrecognized selector sent to class 0xacb12514
2013-09-28 22:29:31.112 UI[60688:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSAlert alloc]: unrecognized selector sent to class 0xacb12514'
*** Call stack at first throw:
(
0 CoreFoundation 0x99b28e8b __raiseError + 219
1 libobjc.A.dylib 0x9617e52e objc_exception_throw + 230
2 CoreFoundation 0x99b2c8ed +[NSObject(NSObject) doesNotRecognizeSelector:] + 253
3 CoreFoundation 0x99a74e87 ___forwarding___ + 487
4 CoreFoundation 0x99a74c32 _CF_forwarding_prep_0 + 50
5 UI 0x00001ff1 main + 71
)
Trace/BPT trap: 5
I can't figure out why it doesn't work, is it something to do with saving the alert class?
Upvotes: 3
Views: 236
Reputation: 55583
As far as I can tell (admittedly I'm no expert in assembly), you are registering the selectors, but never use it.
sel_registerName
is declared like this:
SEL sel_registerName(const char *str);
Behind the scenes, the c-string is interned, and a new pointer (from a hash table of selectors) is returned, which then must be used for future method calls, like this:
SEL alloc_sel = sel_registerName("alloc");
id newObject = objc_msgSend(target_class, alloc_sel);
See Why can't we use C-strings as SELs? as to the why of this question.
Upvotes: 5